Search code examples
scalareduceinfix-operator

Why can't I reduce(+) on a seq of integers in Scala?


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?


Solution

  • 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.