Scala Currying is the process of transforming a function that takes multiple arguments into a single argument.
Consider an example of multiplying two numbers .Open the scala REPL shell and create the multiply method as
1 2 3 4 |
def multiply(a:Int,b:Int) = a*b Output:multiply: (a: Int, b: Int)Int |
The multiply function accepts two arguments a and b of Integer data type and return the result of a*b which is of Integer data type.
Invoke the method as multiply(4,5) and you will get output as res10:Int = 20
Now let us apply the currying for this function as;
1 2 3 |
def multiply(a:Int) = (b:Int) => a*b |
Output: multiply: (a: Int)Int => Int
The multiply function takes a single argument a of Integer data type in the function declaration. Inside the function it takes one more parameter b of Integer data type and return a* b as the result.
Suppose if we invoke the function with single argument the function closure reference is returned as
1 2 3 4 |
multiply(5) res10: Int => Int = <function1> |
Invoke the function by passing two arguments as
1 2 3 4 |
multiply(4)(5) res11:Int = 20 |
Automatic Type Dependent Closure Construction
In scala, parameterless function names allows as parameters of methods. When such methods are called the nullary functions are evaluated and not the actual parameters for the parameterless function names. The nullary function encapsulates computation of the corresponding parameter called call-by-name evaluation.
Let’s look at an example to understand this more clearly.
TypeDependent.scala
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.journaldev.scala object TypeDependent { def main(args: Array[String]) { def forloop(rule: => Boolean)(body: => Unit): Unit = if (rule) { body forloop(rule)(body) } var i = 7 forloop(i > 2) { println("i: " + i) i -= 1 } } } |
We are creating an object TypeDependent
which defines a method “forloop”. This method takes two parameters rule and body. Whenever the formal parameters are used in the body of forloop, the implicitly created nullary functions will be evaluated. Here we are implementing for loop, below image shows the output of above program.
Now let us have a look at more complex example with more operations.
Typedep.scala
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.journaldev.scala object Typedep extends App { def t1(body: => Unit): Criteria = new Criteria(body) protected class Criteria(body: => Unit) { def condition(rule: => Boolean) { body if (!rule) condition(rule) } } var x = 7 t1 { println("x: " + x) x -= 1 } condition (x == 2) } |
We are creating a scala object which contains a method t1 that accepts body parameter of Unit data type and returns an instance of class Criteria. The criteria class defines has a method “condition” which checks the condition if x == 2 after decrementing the value of x. Below image shows the output of the above program.
Personally I don’t like this feature a lot because of complexity, but it’s good to know.