Andriy Drozdyuk
Andriy Drozdyuk

Reputation: 61121

Why is this fold incorrect?

I am reading Programming in Scala, and don't understand why this folding operation is not correct:

val fruit = List("apples", "oranges", "lemons")
println( (0/:fruit)(_.length+_.length) )

I also tried with empty string "" as the starting value - but that didn't compile either:

println( (""/:fruit)(_.length+_.length) )

Upvotes: 3

Views: 176

Answers (3)

huynhjl
huynhjl

Reputation: 41646

println( (0 /: fruit)(_ + _.length) )

The function to pass to the fold takes a function of two arguments (acc, elem) where acc is the accumulator and has the same type as the seed 0, elem has the same type as the elements of the list.

It may be clearer if you use:

(0 /: fruit){ (acc, elem) => acc + elem.length }

(edit: I initially said tuple, I've changed to function of two arguments)

Upvotes: 6

Jean-Philippe Pellet
Jean-Philippe Pellet

Reputation: 60006

Try this:

println( (0 /: fruit)(_ + _.length) )

The passed function receives as argument first the accumulator (an Int, as inferred from your initial value 0) and then the next element of the collection (a String, inferred from the type of fruit).

The order of the arguments is easy to remember, as they correspond to the order in which the initial value and the collection appear. Here, the initial value appears first, and accordingly, the accumulator is passed as first argument — and as second argument, you get an element of the collection fruit, which appears after the method name /:.

If you did a foldRight instead, the order would be conveniently reversed:

println( (fruit :\ 0)(_.length + _) )

Upvotes: 8

JaimeJorge
JaimeJorge

Reputation: 1895

foldLeft (or /:) takes (as second argument) a function which takes two arguments: the accumulator and variable of the type of the members of the list.

So, one should get:

(0/:fruit)((acc:Int,el:String) => acc + el.length)

which is to say

(0/:fruit)(_ + _.length)

Upvotes: 3

Related Questions