The following:
val add = (a: Int, b: Int) => a + b
gets converted to:
object add extends Function2[Int, Int, Int] {
def apply(a: Int, b: Int) = a + b
}
while
val a1 = add(_: Int, 3)
gets converted to:
object a1 extends Function1[Int, Int] {
def apply(x: Int): Int = {
add(x, 3)
}
}
But when I do:
scala> val a2 = add _
a2: () => (Int, Int) => Int = <function0>
And then call a2, it throws an error:
scala> a2(1, 2)
<console>:11: error: too many arguments for method apply: ()(Int, Int) => Int in trait Function0
a2(1, 2)
^
Why is this? Why does the following work?
a2()(1, 2)
add is already a Function2[Int, Int, Int]. If you want a2 to have the same type, then a simple assignment will suffice.
scala> val a2 = add
a2: (Int, Int) => Int = <function2>
scala> a2(1, 2)
res3: Int = 3
What you're thinking of is eta-expansion of a method into a function. If we had:
def add(a: Int, b: Int): Int = a + b
Then, we would use add _ to get the eta-expansion to assign to a value.
scala> def a2 = add _
a2: (Int, Int) => Int
scala> a2(1, 2)
res4: Int = 3
But add is already a function, so the underscore has a different meaning. add is now a value and not a method. Since add is a value, it is like a parameter-less method that returns a Function2[Int, Int, Int]. And if we try to get the eta-expansion of that, we get () => Function2[Int, Int, Int].
Consider a simpler example where we have a simple val a = 1. a is essentially the same as a parameter-less method that returns 1 (def a = 1). If I try to obtain the eta-expansion, I will get () => Int.
scala> val a = 1
a: Int = 1
scala> val a2 = a _
a2: () => Int = <function0>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With