1

I want to get the sum of a seq of Integers 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?

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
hawkeye
  • 34,745
  • 30
  • 150
  • 304

1 Answers1

6

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.

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93