Home > Net >  Scala: How to interpret foldLeft
Scala: How to interpret foldLeft

Time:03-28

I have two examples of foldLeft that I cannot really grasp the logic.

First example:

val donuts: List[String] = List("Plain", "Strawberry", "Glazed")
println(donuts.foldLeft("")((acc, curr) =>  s" $acc, $curr Donut ")) // acc for accumulated, curr for current

This will give

 , Plain Donut , Strawberry Donut , Glazed Donut

Does not foldLeft accumulate value that was earlier? I was expecting the result to be

 , Plain Donut ,  Plain Strawberry Donut , Strawberry Glazed Donut

Second example:

def multi(num:Int,num1:Int):Int=num*10

(1 until 3).foldLeft(1)(multi)

Can someone explain what is happening in every step? I cannot see how this can become 100. Also, the second argument multi is a function. Why does it not take any input variables (num and num1)?

CodePudding user response:

Does not foldLeft accumulate value that was earlier?

yes it does. It uses result of previous iteration and current element and produces new result (using the binary operator you have provided) so for the first example next steps are happening:

  1. the start value of accumulator - ""

  2. acc = "", curr = "Plain" -> " , Plain Donut "

  3. acc = " , Plain Donut ", curr = "Strawberry" -> " , Plain Donut , Strawberry Donut "

  4. acc = " , Plain Donut , Strawberry Donut ", curr = "Strawberry" -> " , Plain Donut , Strawberry Donut , Glazed Donut"

For the second example current value is simply ignored - i.e. multi can be rewritten as def multi(acc:Int, curr:Int):Int = acc*10 where curr is not actually used so foldLeft simply multiplies starting value (1) by 10 n times where n is number of elements in the sequence (i.e. (1 until 3).length which is 2).

Why does it not take any input variables (num and num1)?

foldLeft is a function which accepts a function. It accepts a generic function which in turn accepts two parameters and returns result of the same type as the first parameter (op: (B, A) => B, where B is the the result type and A is sequence element type). multi matches this definition when B == A == Int and is passed to the foldLeft which will internally provide the input variables on the each step.

CodePudding user response:

A left fold needs three things: a list to works on, an initial value, and a function.

That function takes each element of the list and applies it to the initial value. Each time, the initial value is the result of the previous fucntion application.

Summing a list is a great toy example.

val nums = List(1, 2, 3, 4)
val total = nums.foldLeft(0)((a, b) => a   b)

total is 10.

That initial value has to pass all of the state you need. Currently, you pass the accumulated string. What you should be passing is a tuple giving your function extra information to work with: the accumulated string, and a string representing the previous element in the list.

Your result would look something like:

("Plain donut, ...", "Glazed")

Then you just need to select out the accumulated string and discard the second element.

  • Related