scalapartially-applied-type

Returning a partially applied function in Scala


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?


Solution

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