Scala foldLeft on Maps
Asked Answered
H

4

40

How do you use Map.foldLeft? According to the docs it looks like

foldLeft [B] (z: B)(op: (B, (A, B)) ⇒ B) : B

But I'm having difficulty:

Map("first"->1,"second"->2).foldLeft(0)((a,(k,v)) => a+v )

error: not a legal formal parameter

The error points to the open bracket in front of k.

Hydrolysis answered 14/11, 2010 at 17:34 Comment(0)
L
93

If you want to use the (a, (k, v)) syntax, you need to advise the compiler to use pattern matching.

Map("first"->1, "second"->2).foldLeft(0){ case (a, (k, v)) => a+v }

Note that a case statement requires curly braces.

London answered 14/11, 2010 at 18:10 Comment(1)
Why is pattern matching required? Are there any other patterns which can be matched for in a foldLeft ?Arondell
C
18

I think, you can't do the pattern match on tuples as you expect:

Map("first"->1,"second"->2).foldLeft(0)((a, t) => a + t._2)

Actually, using values and sum is simpler.

Map("first"->1,"second"->2).values.sum
Coles answered 14/11, 2010 at 17:47 Comment(3)
He can pattern match on tuples. To pattern match, though, one needs to use case.Biotype
@Daniel That's the advantage of my lawyer-like sentence: it's correct (he cannot pattern-match as he expected) but I've forgotten the case syntax.Coles
For problems like this though, using values or mapValues is absolutely the clearest solution (which will almost always make it the right choice)Musil
U
8

The trick is to use a partial function as the code block, in other words you add a case statement that matches on the arguments:

Map("first" -> 1, "second" -> 2).foldLeft(0) { case (a, (k, v)) => a + v }
Unconquerable answered 14/11, 2010 at 20:52 Comment(1)
Thank you sooo much Theo! This is what I've been looking for a while...but how can case be used without match keyword and how come is it being used as destructing action?Melt
D
4

This is not really an answer to your question but I found it useful when starting out with folds, so I'll say it anyway! Note that the /: method "alias" for foldLeft can be clearer for two reasons:

xs.foldLeft(y) { (yy, x) => /* ... */ }

(y /: xs) { (yy, x) => /* ... */ }

Note that in the second line:

  • it's more clear that the value y is being folded into the collection xs
  • you can easily remember the ordering of the Tuple2 argument is the same as the ordering of the method "call"
Downtoearth answered 14/11, 2010 at 19:55 Comment(1)
1 - far from clear, it is misleading seen that you exchange folded object with its result; 'folding' implies action on the collection, and so y is starting value and yy is is the result of that fold. 2 - the ordering depends on the direction - first, on the left, if foldLeft, or second, on the right, if foldRight || anyway finally deprecated. Scala progress is steady because attention is paid on common sense and collaboration aspects.Admittance

© 2022 - 2024 — McMap. All rights reserved.