Having a function f
defined as:
def f(i1: Int, i2: Int)(i3: Int) = i1 + i2 + i3
It is possible to define a partially applied function as follows using _
:
val f12 = f(1, 2) _ // f12: Int => Int = <function>
f12(3) // res0: Int = 6
Now when I return a partially applied function from a function, I do not need to use _
:
def f23(f: (Int, Int) => Int => Int) = f(2, 3) // f23: (f: (Int, Int) => Int => Int)Int => Int
val f23f = f23(f) // f23f: Int => Int = <function>
f23f(4) // res1: Int = 9
If I place _
at the f23
definition I will get an Error:
def f23(f: (Int, Int) => Int => Int) = f(2, 3) _
Error:(6, 49) _ must follow method; cannot follow Int => Int
def f23(f: (Int, Int) => Int => Int) = f(2, 3) _
What is the reason for this inconsistency?
f
is a method, not a function. You can read about some of the differences here.
f12
is a function derived from f
via eta-expansion. It is not a partial function. A PartialFunction
is a function defined over a limited domain of input values. If, say, f12
was defined only for Int
values less than 500, for example, and undefined for input values greater than 500, then it would be a partial function.
def f23(f: (Int, Int) => Int => Int) = f(2, 3) _
This fails because f
, as defined here, is a function that takes 2 Int
values and returns a function that takes an Int
and returns an Int
. In this situation what is the underscore supposed to be standing in for? f(2,3)
is a complete invocation that returns an Int=>Int
function. It's a bit like writing 5 + 7 _
. It's not clear what the _
is substituting for.
You can, on the other hand, do this: ... = f(2,3)(_)
. Then it's clear that the returned function is being invoked with a missing, i.e. _
, parameter. Which is the same thing as: ... = f(2,3)
.