1

I’m learning scala and read this concept called ‘currying’. I know it is used to divide the parameters in a function and pass them one by one. So from what I understood I tried creating a simple basic currying function below:

def add_num(a:Int,b:Int)(c:Int):Int={a+b+c}
add_num(10,20)
add_num(10)

But it gives me an error when I call the function with values 10 and 20. What i understood is it will remember the values and then I can pass the third value as 10 separately. I’m unable to understand this concept. Can someone help me in understanding this concept in most basic terms.

Error is missing argument list for method add_num. Unsupplied methods are only converted to functions when a function type is executed.

Vyom Verma
  • 103
  • 1
  • 5
  • 1
    Does this answer your question? [Curried function in scala](https://stackoverflow.com/questions/18398574/curried-function-in-scala) – Ivan Stanislavciuc Jun 18 '20 at 11:16
  • 3
    Try `val almost = add_num(10,20) _` followed by `almost(7)`. – jwvh Jun 18 '20 at 11:16
  • I tried this val f = add_num(10,20)(_) f(10) and it gave me the result as 40. But I don’t understand why do I have to use a placeholder and then passing its value, what is the benefit of currying if I still have to use it like this. – Vyom Verma Jun 18 '20 at 11:32
  • 3
    The benefit is that you now have the partially applied function as a separate object in a variable and can give that to some other part of your application that does not need to know about the first two parameters. Consider that your function calls an API. The part of your application that sets up credentials could curry a function to pass in the API access key. The rest of the application does then not need to care about that anymore. – Thilo Jun 18 '20 at 11:40
  • 1
    @VyomVerma The point of currying is not to apply all the arguments at once, it's to be able to pass `almost` to other places in your program like `Thilo` said. If you want to give all arguments at once, you can still use `add_num(10,20)(7)`! – francoisr Jun 18 '20 at 11:45

1 Answers1

6

A curried function is applied to multiple argument lists, instead of just one. An example of a non-curried function, which adds two Int parameters, x and y:

scala> def plainOldSum(x: Int, y: Int) = x + y
plainOldSum: (x: Int, y: Int)Int
scala> plainOldSum(1, 2)
res4: Int = 3

A similar function that’s curried:

scala> def curriedSum(x: Int)(y: Int) = x + y
curriedSum: (x: Int)(y: Int)Int
scala> curriedSum(1)(2)
res5: Int = 3

What's happening here is that when you invoke curriedSum, you actually get two traditional function invocations back-to-back. The first function invocation takes a single Int parameter named x, and returns a function value for the second function. This second function takes the Int parameter y.

Here's a function named first that does in spirit what the first traditional function invocation of curriedSum would do:

scala> def first(x: Int) = (y: Int) => x + y
first: (x: Int)Int => Int

Applying the first function to 1—in other words, invoking the first function and passing in 1—yields the second function:

scala> val second = first(1)
second: Int => Int = <function1>

Applying the second function to 2 yields the result:

scala> second(2)
res6: Int = 3

These first and second functions are just an illustration of the currying process. They are not directly connected to the curriedSum function. Nevertheless, there is a way to get an actual reference to curriedSum's "second" function. You can use the placeholder notation to use curriedSum in a partially applied function expression, like this:

scala> val onePlus = curriedSum(1)_
onePlus: Int => Int = <function1>

The underscore in curriedSum(1)_ is a placeholder for the second parameter list.2 The result is a reference to a function which, when invoked, adds one to its sole Int argument and returns the result:

scala> onePlus(2)
res7: Int = 3

And here's how you'd get a function that adds two to its sole Int argument:

scala> val twoPlus = curriedSum(2)_
twoPlus: Int => Int = <function1>
scala> twoPlus(2)
res8: Int = 4
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Raphael
  • 92
  • 10
  • 3
    This is a really clear explanation, and an exceptional first post. The Stack Overflow community is lucky to have you as a contributor. – Jeremy Caney Jun 18 '20 at 19:09