Hugo S Ferreira Hugo S Ferreira - 11 months ago 43
Scala Question

Usefulness (as in practical applications) of Currying v.s. Partial Application in Scala

I'm trying to understand the advantages of currying over partial applications in Scala. Please consider the following code:

def sum(f: Int => Int) = (a: Int, b: Int) => f(a) + f(b)

def sum2(f: Int => Int, a: Int, b: Int): Int = f(a) + f(b)

def sum3(f: Int => Int)(a: Int, b: Int): Int = f(a) + f(b)

val ho = sum({identity})
val partial = sum2({ identity }, _, _)
val currying = sum3({ identity })

val a = currying(2, 2)
val b = partial(2, 2)
val c = ho(2, 2)

So, if I can calculate partially applied function that easy, what are the advantages of currying?

Answer Source

Currying is mostly used if the second parameter section is a function or a by name parameter. This has two advantages. First, the function argument can then look like a code block enclosed in braces. E.g.

using(new File(name)) { f =>

This reads better than the uncurried alternative:

using(new File(name), f => {

Second, and more importantly, type inference can usually figure out the function's parameter type, so it does not have to be given at the call site. For instance, if I define a max function over lists like this:

def max[T](xs: List[T])(compare: (T, T) => Boolean)

I can call it like this:

max(List(1, -3, 43, 0)) ((x, y) => x < y)

or even shorter:

max(List(1, -3, 43, 0)) (_ < _)

If I defined max as an uncurried function, this would not work, I'd have to call it like this:

max(List(1, -3, 43, 0), (x: Int, y: Int) => x < y)

If the last parameter is not a function or by-name parameter, I would not advise currying. Scala's _ notatation is amost as lightweight, more flexible, and IMO clearer.