Check out my video on Scala for comprehensions here.
Category: Java & Scala
Scala fold, foldLeft and foldRight
foldLeft
1 2 |
val letters = List("a", "b", "c") letters.foldLeft(" ") { (m: String, n: String) => m + n } will output 'abc'. |
foldLeft takes 2 parameters. First one is a starting value, an empty string in our case. Second one is a function { (m: String, n: String) => m + n } , which in turn takes 2 parameters.
The first parameter (m) is an accumulator with an initial value of ” “. The second parameter (n) is the value from the list starting with “a”.
The following are the values for parameters m, n and the result at the end of each iteration.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
1st iteration ------------- Starts with " " and adds 'a' from the list. m:" " n: a = a 2nd iteration ------------- Starts with the result of the 1st iteration 'a' and adds 'b' from the list. m: a n: b = ab 3rd iteration ------------- Starts with the result of the 2nd iteration 'ab' and adds 'c' from the list. m: ab n: c = abc |
Note:
The start value is passed as the first parameter to the function and list is evaluated from left to right.
foldRight
1 2 |
val letters = List("a", "b", "c") letters.foldRight("") { (m: String, n: String) => m + n } will output 'abc'. |
foldRight takes 2 parameters. First one is a starting value, an empty string. Second one is a function { (m: String, n: String) => m + n }‘ , which in turn takes 2 parameters.
The First parameter (m) is the value from the list starting with “c“. The second parameter (n) is an accumulator starting with the start value ” “. This is different from foldLeft.
The following are the values for parameters m, n and result at the end of each iteration.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
1st iteration -------------- Starts with 'c' from the list and adds the start value " ". m: c n:" " = c 2nd iteration ------------- Starts with 'b' from the list and adds result from 1st iteration 'c'. m: b n: c = bc 3rd iteration ------------- Starts with 'a' from the list and adds result from 2nd iteration 'bc'. m: a n: bc = abc |
Note:
The start value is passed as the second parameter to the function and list is evaluated from right to left. This is different from foldLeft.
fold
fold works same as above, except the order in which operations are performed is unspecified, because of this, there are 2 additional conditions on
- Starting value must be neutral. e.g., Nil for list concatenation, 0 for addition, or 1 for multiplication. This is necessary as fold operation can work in parallel.
Fold is done on supertype of values in a given collection.
1 2 |
val letters = List("a", "b", "c") letters.foldRight("") { (m: String, n: String) => m + n } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Iteration A ------------ Starts with " " and adds 'a' from the list. m:"" n: a = a ------------- Iteration B in parallel with Iteration A Starts with " " and adds 'b' from the list. m:"" n: b = b Iteration C in parallel with Iteration B and Iteration A -------------------------------------------------------- Starts with " " string and adds 'b' from the list. m:"" n: c = c output abc |
Nested Functions and Methods in Scala
In Scala, you can nest methods and functions inside a method. This is a useful feature when you want to encapsulate a part of the logic specific to the enclosing method. The following is an example of a nested method.
1 2 3 4 5 6 7 |
def mainMethod (x: String) = { def nestedMethod(y:String, z: String) = { println(y + z) } nestedMethod(x," a nested method") } println(mainMethod("I am")) |
When you run this code, it will print ‘I am a nested function’.
Similarly, you can do nested functions as below.
1 2 3 4 5 6 |
def mainMethod (x: String) = { val nestedFucntion = (y: String, z: String) => println(y + z) nestedFucntion(x," a nested function") } println(mainMethod("I am")) |
Passing Functions as Parameters in Scala & Java
Passing a function as a parameter helps in dividing complexity logically. For example, a function that iterates through a list of words and converts them to the upper case can be passed to any method that needs this functionality without exposing the list. It lets you delegate the complexity to the function. Here is the code both in Scala and Java.
Scala
First define a method that takes a function as a parameter.
1 2 3 |
def methodA(fn: () => String): String = { fn() } |
The above function fn, takes no parameters and outputs a String. Let’s define a function that takes no parameters and outputs a String, so we can pass it to methodA.
1 |
val functionB = () => "Hi, I am functionB from Scala, I am passed to functionA as a parameter." |
Pass functionB to functionA as below.
1 2 3 |
def message: String = { methodA(functionB) } |
You should see “Hi, I am
Let’s implement the same thing in Java.
Java
1 2 3 4 5 6 7 8 9 10 |
@FunctionalInterface public interface IFunc { String printMessage (); } public String methodA(IFunc funcB) { return funcB.printMessage(); } IFunc functionB = () -> "Hi, I am functionB from Java, I am passed to functionA as a parameter."; |
Pass functionB to functionA as below.
1 2 3 |
public String message() { return methodA(functionB); } |
You should see “Hi, I am