Home > Back-end >  what is the [B] in "def foldLeft[B](z: B)(op: (B, A) ⇒ B): B"?
what is the [B] in "def foldLeft[B](z: B)(op: (B, A) ⇒ B): B"?

Time:03-29

Immediately following foldLeft there is that [B] and I don't understand what it is.

I believe that it refers to the type of whatever it's operating on. Is it like a receiver in golang?

CodePudding user response:

Using foldLeft we are folding a foldable container containing element(s) of type A to produce an output of type B. z is the initial value and op is a function that takes two arguments of types B and A to produce a B. If the container is not empty, the folding process begins with z and an element from the container as inputs for op. This process continues with the result of op along with the next element from the container eventually producing a result of type B. If the container is empty, z, which is also of type B, is the result of foldLeft.

Eg: A list with different initial values and operations:

val ls = List(1, 2, 3)

ls.foldLeft(0)((acc, int) => acc   int) //6
ls.foldLeft(2)((acc, int) => acc   int) //8
ls.foldLeft("")((acc, int) => acc   int) //"123"
ls.foldLeft(List.empty[Int])((acc, int) => int :: acc) //List(3, 2, 1)

Here the type of z and the type of the result for a particular case is the same but varies over other cases. In scala, we can use a type parameter to represent this. In the case of foldLeft it is represented using [B]:

def foldLeft[B](z: B)(op: (B, A) => B): B

We could have written the above examples like:

ls.foldLeft[Int](0)((acc, int) => acc   int) 
ls.foldLeft[Int](2)((acc, int) => acc   int) 
ls.foldLeft[String]("")((acc, int) => acc   int) 
ls.foldLeft[List[Int]](List.empty[Int])((acc, int) => int :: acc) 

But, as the compiler could infer the type B from the value of z, this was not necessary.

CodePudding user response:

The way I like to explain foldLeft is that it's like doing this:

var result = 0;
for (var i of myCollection) {
  result  = i;
}
return result

[B] is a type parameter on the method, and it refers to the type of your result (in this case, Int), which is the same type as the "initial value" that you declare before your for-loop. [A] is the type of the values in myCollection (var i, which is also Int in my example).

Thinking about this code in very generic terms, you provide some initial state (result = 0), then in each step of the for-loop, you take an element from the collection, and apply some logic to combine that element with the current "state" to get the next state.

With foldLeft, z: B is the "initial state", and op: (A, B) => B is a function to combine an element from the collection (A) with the current state (B) and returns the next state.

So the code above could be rewritten as

myCollection.foldLeft(0) { (sum, next) => sum   next }

Or, using convenient shorthand for anonymous functions,

myCollection.foldLeft(0)(_   _)
  • Related