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