I want to get the sum of a seq
of Integer
s in Scala.
In my mind I want to fold a plus over the integers like this:
val seqOfIntegers:Seq[Int] = Seq(1, 2, 3, 4, 5)
val sumOfIntegers = seqOfIntegers.reduce(+)
This isn't valid.
Instead I have to do:
val sumOfIntegers = seqOfIntegers.reduce(plus)
...
def plus(a:Integer, b:Integer): Integer = { a + b}
(I'm sure you could sugar that up - but my point is that the original plus symbol doesn't work as a function, and the errors messages don't make it clear why.)
My question is: Why can't I reduce(+) on a seq of integers in Scala?
That's because +
is not a function (that is, an object of type Function2[Int, Int, Int]
, which is the same as (Int, Int) => Int
). Instead, it's a method on Int
, which takes another Int
and returns an Int
. That is, what you want to pass to reduce
is
actually (a: Int, b: Int) => a.+(b)
, which can be sugared into (a: Int, b: Int) => a + b
and then _ + _
.
That is,
seq.reduce(_ + _)
would work as expected.
Making .reduce(+)
work
If you want to pass +
as argument, you have to define a value +
that extends (Int, Int) => Int
. For example:
object + extends ((Int, Int) => Int) { def apply(a: Int, b: Int): Int = a + b }
Seq(1,2,3,4,5).reduce(+)
// res0: Int = 15
or, additionally relying on eta-expansion:
def +(a: Int, b: Int) = a + b
Seq(1,2,3,4,5).reduce(+)
So, you can invoke .reduce(+)
on sequences, you just need either a value +
of the right type (Int, Int) => Int
(a value, not a method), or you need a binary method +
in scope, which takes two integers, and can be eta-expanded into (Int, Int) => Int
.
On error messages
The error messages seem quite unambiguous. If I don't define +
myself, and enter
Seq(1, 2).reduce(+)
into the console, then I get
error: not found: value +
because there is no value +
anywhere. I don't know how the error message could be any clearer.