0

I was just watching lecture 2.2 Higher order functions (for the Functional programming principles in Scala). There, a sum function is defined like this:

def sum(f: Int => Int, a: Int, b: Int) { ... }

Later on, the same function is defined like this:

def sum(f: Int => Int)(a: Int, b: Int) { ... }

They seem to be equivalent, but no explanation is given why to choose on over the over.

helpermethod
  • 59,493
  • 71
  • 188
  • 276
  • Also of note is that when you are using generics, generic type parameters bind one parameter block at a time. So if you `def f[A](x: A, y: A)` then `A` will be chosen to match the types of both `x` and `y`, while `def f[A](x: A)(y: A)` means that the type of `A` will be the type of `x`, and `y` had better match. Either behavior can be useful. – Rex Kerr Sep 27 '12 at 10:01

2 Answers2

2

The second definition declares a method with two argument lists. Ignoring implicits, then this is usually used to enable curried function applications. The basic idea is that you can bind some parameters of a function, which yields another function with fewer arguments left, namely the ones that are not yet bound. Here is a simple text book example:

def add(xs: List[Int])(y: Int) =
  xs.map(_ + y)

// Bind first argument and store resulting function in f
val f = add(List(2,3,5,7,11))_

println(f(0))  // List(2, 3, 5, 7, 11)
println(f(10)) // List(12, 13, 15, 17, 21)

// Bind first argument and store resulting function in g
val g = add(List(0,1,0,1,0,1))_

println(g(1))  // List(1, 2, 1, 2, 1, 2)
println(g(-1)) // List(-1, 0, -1, 0, -1, 0)

// Regular invocation
println(add(List(1,2,3))(4)) // List(5, 6, 7)

You'll find plenty of articles about currying online, for example, how to use currying in Scala, or that there are multiple ways to curry in Scala.

Regarding why to choose one over the over: In Haskell you would basically always choose the curried version over the uncurried one since the latter gives you the advantage of being able to partially bind parameters, and since there is no "syntax penalty" or runtime penalty for using curried versions. Since this is not true for Scala (as you can observe from the above code snippet when it comes to syntax), you might probably want to prefer the uncurried style except if you know that the most likely use cases of your methods/functions would benefit from currying.

Community
  • 1
  • 1
Malte Schwerhoff
  • 12,684
  • 4
  • 41
  • 71
1

Sort of, but not exactly. The biggest difference is that having multiple parameter lists allows us to more easily use the function without specifying all of the parameters.

For an example, let's define your two functions like this:

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

Now lets define a function g that takes, as parameter, another function that takes two Ints and produces an Int

def g(f: (Int, Int) => Int) = f(3, 5)

The version of sum with multiple parameter lists allows us to just specify the parameters of the first list and then pass this partially-applied function to g:

g(sum2(_ + 1))

This is very simple and very clean.

Without the separate parameter lists, as in sum1, we have to write a lambda expression to show where the a and b parameters come from:

g((a: Int, b: Int) => sum1(_ + 1, a, b))
dhg
  • 52,383
  • 8
  • 123
  • 144