Partially Applied Functions and Curry

Partially Applied Functions

When you invoke a scala function, you need to apply the arguments to the function. If you pass all the expected arguments, you say the function is fully applied. If you only send only a few of arguments, the function is called partially applied function. The partially applied function in scala brings us the convenience of binding some arguments and leaving the rest to be filled in later.

Below is an example of partially applied function in scala.

1
2
3
4
5
6
7
8
9
10
11
scala> def sum(a:Int, b:Int, c:Int) = a + b + c
sum: (a: Int, b: Int, c: Int)Int

scala> var sum1 = sum(1, 2, _:Int)
sum1: Int => Int = <function1>

scala> sum1(3)
res0: Int = 6

scala> sum(1, 2, 3)
res1: Int = 6

In the above example, sum1 is partially applied for the first 2 arguments. Whenever you want to omit all the argument in the function, such as doing var sum1 = sum(_:Int, _:Int, _:Int), you can use <function> _ to present as follows. Actually, partially applied function has an apply method, so you can leverate the short-cut function call.

1
2
3
4
5
6
7
8
scala> var sum2 = sum _
sum2: (Int, Int, Int) => Int = <function3>

scala> sum2(1, 2, 3)
res2: Int = 6

scala> sum2.apply(1, 2, 3)
res3: Int = 6

Sometimes, we need to pay more attention when using overrided function as partially applied function as following example.

1
2
3
4
5
scala> val k = println _
k: () => Unit = <function0>

scala> k(3)
<console>:9: error: too many arguments for method apply: ()Unit in trait Function0 k(3)

The reason we why println _ is of type () => Unit instead of Any => Unit is because there exists an overloaded definition of println that doesn’t take any parameters in scala source code:

1
def println() = Console.println()

In order to use the println that takes a parameter, you have to explicitly tell the compiler to choose it as follows.

1
2
3
4
5
scala> val k = println(_: Any)
k: Any => Unit = <function1>

scala> k(3)
3

Currying Functions

Currying, invented by Moses Schönfinkel and Gottlob Frege, is the technique of transforming a function that takes multiple arguments into a function that takes a single argument (the other arguments having been specified by the curry). Below is an example of function curry.

1
2
3
4
5
scala> def add(x:Int)(y:Int) = x + y
add: (x: Int)(y: Int)Int

scala> add(1)(2)
res7: Int = 3

In addition, an anonymous function returned from another function can be also curried as follows.

1
2
3
4
5
scala> def add2(x:Int) = (y:Int) => x + y
add2: (x: Int)Int => Int

scala> add2(1)(2)
res8: Int = 3

You can also convert a regular function to its curried version through partially applied function as following example. add4 is a curried function from partially applied function add3.

1
2
3
4
5
6
7
8
scala> def add3(x:Int, y:Int) = x + y
add3: (x: Int, y: Int)Int

scala> val add4=(add3 _).curried
add4: Int => (Int => Int) = <function1>

scala> add4(1)(2)
res9: Int = 3

Most of time, we actually use in the other way by creating a specialized version of generalized function through curry function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
scala> def filterBy(f: Int => Boolean)(xs: List[Int]) = {xs filter f}
filterBy: (f: Int => Boolean)(xs: List[Int])List[Int]

scala> def even(x: Int) = x % 2 == 0
even: (x: Int)Boolean

scala> val xs = List(1, 3, 4, 5, 12, 6, 7)
xs: List[Int] = List(1, 3, 4, 5, 12, 6, 7)

scala> val ts = List(1, 2, 3, 4, 15, 8, 9)
ts: List[Int] = List(1, 2, 3, 4, 15, 8, 9)

scala> val evenFilter = filterBy(even) _
evenFilter: List[Int] => List[Int] = <function1>

scala> evenFilter(xs)
res10: List[Int] = List(4, 12, 6)

scala> evenFilter(ts)
res12: List[Int] = List(2, 4, 8)

For more tips about scala, please refer to the scala tip.