Function currying in scala - scala

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.

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

Related

Understanding currying Scala [duplicate]

This question already has answers here:
Understanding Currying in Scala
(3 answers)
Closed 4 years ago.
def sum(f: Int => Int): (Int, Int) => Int = {
def sumF(a: Int, b: Int): Int =
if (a > b) 0
else f(a) + sumF(a + 1, b)
sumF
}
def sumCubes = sum(a => a * a * a)
sumCubes // output Function2
sumCubes(1,10) // output 3025.
sumCubes() // doesn't work
I feel I dont understand currying well enough. In the first statement , we are calling sumCubes without parameters , hence sum gets called with the anonymous function as parameter and returns a function2.
Whats really happening in 2nd and 3rd invocation ,
Why are we able to do
sum(a => a * a * a)(1,10)
but not
sumCubes()(1,10)
My understanding is that in sum(a => a * a * a)(1,10) , we are partially applying sum to the anonymous function, which returns a Function2 ,which is applied to the second pair of parameters (1,10) and hence we are getting 3025,
However the same should happen in case of sumCubes()(1,10) , invoking sumCubes without parameters first , would inturn invoke sum with the anonymous function and the Function2 returned would be applied to (1,10)
Why does sumCubes(1,10) work but not sumCubes()(1,10) , shouldn't sumCubes and sumCubes() mean the same thing , invocation of function sumCubes. Also if a simple reference sumCubes is invoking it , how can I pass it around. I feel like I am not understanding something fundamental about Scala.
Scala's methods can have multiple argument lists.
For example, here is a method foo that has ten argument lists, of which the first seven are empty:
def foo()()()()()()()(a: Int)(b: Int)(c: Int): Int = a + b + c
You can invoke it as follows:
println(foo()()()()()()()(1)(20)(300))
and it will print 321.
Note that when you invoke a method, the number of argument lists, as well as the number of arguments in each list (and also their types) have to match the declaration.
Another example. The following method has two argument lists:
def bar(i: Int)(f: Int => Int) = f(i)
you can invoke it as follows:
bar(42)(x => x * x)
but not as
bar()(x => x * x)
bar()(42)(x => x * x)
bar(42)()
or anything like it.
Completely analogously, if you have defined a method with zero argument lists
def baz = (x: Int) => x * x
then you must invoke it with zero argument lists too:
baz
Since it returns an Int => Int function, you can of course apply the result to an Int:
baz(42)
which is the same as (baz)(42), but you cannot do the following:
baz()(42)
because baz itself has no argument lists, and () does not contain a single integer argument.
Note that all of the above is actually a simplification: under certain circumstances, methods that have an empty argument list can be called without parentheses, i.e. def foo(): Unit = ... can be invoked as foo, without (). This is a somewhat strange feature, and I can't say exactly why it's there. My best guess would be: it has something to do with java-interop, where you really want to omit parentheses on zero-ary getters.

Scala: Difference between function declarations [duplicate]

This question already has answers here:
Differences between these three ways of defining a function in Scala
(3 answers)
Closed 6 years ago.
I am new to Scala, below are three function declarations that are confusing to me:
First
scala> def sum = (a: Int, b: Int) => a + b
sum: (Int, Int) => Int
Second
scala> def sum (a: Int, b: Int) = a + b
sum: (a: Int, b: Int)Int
Third
scala> val sum = (a: Int, b: Int) => a + b
sum: (Int, Int) => Int = <function2>
I know that the second one is method, third one is a function literal. My confusion is with the first declaration, is it a normal function or is it a some other syntax that I do not understand? An explanation would be appreciated.
EDIT
Also, when I try to create a partially applied function using the first declaration I get this:
scala> val anotherSum = sum _
anotherSum: () => (Int, Int) => Int = <function0>
Which I expected to be of type Function2 as sum has 2 parameters.
The first and second declarations declare different things. It's not the same thing with different syntax.
scala> def sum = (a: Int, b: Int) => a + b
sum: (Int, Int) => Int
Here, you define a method named sum that takes no parameters and returns a function that takes two Int parameters and returns an Int.
So, sum is a method that returns a function that adds two numbers.
scala> def sum (a: Int, b: Int) = a + b
sum: (a: Int, b: Int)Int
Here, you define a method named sum that takes two Int parameters and that returns an Int.
So, sum is a method that adds two numbers.
The difference is that in the first version, sum takes no parameters and returns a function, and in the second, sum takes two parameters and returns an Int. Two very different things!
The third:
scala> val sum = (a: Int, b: Int) => a + b
sum: (Int, Int) => Int = <function2>
Here you define a value named sum that is a Function2, in other words, a function that takes two Int parameters and returns an Int.
So, sum is a value that is of type Function2, and refers to a function that adds two numbers.
Extra:
scala> val anotherSum = sum _
anotherSum: () => (Int, Int) => Int = <function0>
Look carefully at the type. anotherSum is a function that takes no parameters that returns a function that takes two Int parameters that returns an Int.
You are not partially applying anything here. Section 6.7 Method Values of the Scala Language Specification explains what happens here.

Difference between these two scala function definitions

I am going through the Scala School basics tutorial at
https://twitter.github.io/scala_school/basics.html.
I am trying to understand what the difference between these two definitions is.
Also, if someone could explain currying vs partial application in this context.
def multiply(m: Int)(n: Int): Int = m * n
and
def multiply(m: Int,n: Int): Int = m * n
The difference is only in how you actually call this methods. In second case your only choice is to pass both arguments at the same time, like multiply(2,2). In first case you can pass one argument and get function Int => Int and then call it with another argument:
val f: Int => Int = multiply(2) _
f(2) // 4
f(3) // 6
f(525) // 1050
The real power of curried methods is when the second argument is implicit so you don't have to pass it explicitly.
implicit val x = 2
def multiply(m: Int)(implicit n: Int): Int = m * n
multiply(5) //10

Curried update method

I'm trying to have curried apply and update methods like this:
def apply(i: Int)(j: Int) = matrix(i)(j)
def update(i: Int, j: Int, value: Int) =
new Matrix(n, m, (x, y) => if ((i,j) == (x,y)) value else matrix(x)(y))
Apply method works correctly, but update method complains:
scala> matrix(2)(1) = 1
<console>:16: error: missing arguments for method apply in class Matrix;
follow this method with `_' if you want to treat it as a partially applied function
matrix(2)(1) = 1
Calling directly update(2)(1)(1) works, so it is a conversion to update method that doesn't work properly. Where is my mistake?
The desugaring of assignment syntax into invocations of update maps the concatenation of a single argument list on the LHS of the assignment with the value on the RHS of the assignment to the first parameter block of the update method definition, irrespective of how many other parameter blocks the update method definition has. Whilst this transformation in a sense splits a single parameter block into two (one on the LHS, one on the RHS of the assignment), it will not further split the left parameter block in the way that you want.
I also think you're mistaken about the example of the explicit invocation of update that you show. This doesn't compile with the definition of update that you've given,
scala> class Matrix { def update(i: Int, j: Int, value: Int) = (i, j, value) }
defined class Matrix
scala> val m = new Matrix
m: Matrix = Matrix#37176bc4
scala> m.update(1)(2)(3)
<console>:10: error: not enough arguments for method update: (i: Int, j: Int, value: Int)(Int, Int, Int).
Unspecified value parameters j, value.
m.update(1)(2)(3)
^
I suspect that during your experimentation you actually defined update like so,
scala> class Matrix { def update(i: Int)(j: Int)(value: Int) = (i, j, value) }
defined class Matrix
The update desugaring does apply to this definition, but probably not in the way that you expect: as described above, it only applies to the first argument list, which leads to constructs like,
scala> val m = new Matrix
m: Matrix = Matrix#39741f43
scala> (m() = 1)(2)(3)
res0: (Int, Int, Int) = (1,2,3)
Here the initial one-place parameter block is split to an empty parameter block on the LHS of the assignment (ie. the ()) and a one argument parameter block on the RHS (ie. the 1). The remainder of the parameter blocks from the original definition then follow.
If you're surprised by this behaviour you won't be the first.
The syntax you're after is achievable via a slightly different route,
scala> class Matrix {
| class MatrixAux(i : Int) {
| def apply(j : Int) = 23
| def update(j: Int, value: Int) = (i, j, value)
| }
|
| def apply(i: Int) = new MatrixAux(i)
| }
defined class Matrix
scala> val m = new Matrix
m: Matrix = Matrix#3af30087
scala> m(1)(2) // invokes MatrixAux.apply
res0: Int = 23
scala> m(1)(2) = 3 // invokes MatrixAux.update
res1: (Int, Int, Int) = (1,2,3)
My guess is, that it is simply not supported. Probably not due to an explicit design decision, because I don't see why it shouldn't work in principle.
The translation concerned with apply, i.e., the one performed when converting m(i)(j) into m.apply(i, j) seems to be able to cope with currying. Run scala -print on your program to see the code resulting from the translation.
The translation concerned with update, on the other hand, doesn't seem to be able to cope with currying. Since the error message is missing arguments for method apply, it even looks as if the currying confuses the translator such that it tries to translate m(i)(j) = v into m.apply, but then screws up the number of required arguments. scala -print unfortunately won't help here, because the type checker terminates the translation too early.
Here is what the language specs (Scala 2.9, "6.15 Assignments") say about assignments. Since currying is not mentioned, I assume that it is not explicitly supported. I couldn't find the corresponding paragraph for apply, but I guess it is purely coincidental that currying works there.
An assignment f(args) = e with a function application to the left of
the ‘=’ operator is interpreted as f.update(args, e), i.e. the
invocation of an update function defined by f.

What are the applications/advantages of using partially applied functions in scala?

We have partially applied functions in Scala-
def sum(a:Int,b:Int,c:Int) = a+b+c
val partial1 = sum(1,_:Int,8)
I was wondering what are the advantages of using Partially applied functions. Or is it just a syntactical addition?
About partially applied function in general, the book "Programming in Scala, 2nd edition" mentions:
Another way to think about this kind of expression, in which an underscore
is used to represent an entire parameter list, is as a way to transform a
def into a function value.
For example, if you have a local function, such as sum(a: Int, b: Int, c: Int): Int, you can “wrap” it in a function value whose apply method has the same parameter list and result types.
scala> def sum(a: Int, b: Int, c: Int) = a + b + c
sum: (a: Int,b: Int,c: Int)Int
scala> val a = sum _
a: (Int, Int, Int) => Int = <function3>
(Here, a(1, 2, 3) is a short form for:
scala> a.apply(1, 2, 3)
res12: Int = 6
)
Although you can’t assign a method or nested function to a variable, or pass it as an argument to another function, you can do these things if you wrap the method or nested function in a function value by placing an underscore after its name.
The advantage is that sum(1,_,8) is less to type and read than x => sum(1,x,8).
That's all there is to it.
sum(1,_,8) is less to type and read than x => sum(1,x,8)
However, neither is legal; you must provide the parameter type.