Writing functions of tuples conveniently in Scala
Asked Answered
M

6

26

Quite a few functions on Map take a function on a key-value tuple as the argument. E.g. def foreach(f: ((A, B)) ⇒ Unit): Unit. So I looked for a short way to write an argument to foreach:

> val map = Map(1 -> 2, 3 -> 4)

map: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4)

> map.foreach((k, v) => println(k))

error: wrong number of parameters; expected = 1
       map.foreach((k, v) => println(k))
                          ^

> map.foreach({(k, v) => println(k)})

error: wrong number of parameters; expected = 1
       map.foreach({(k, v) => println(k)})
                           ^

> map.foreach(case (k, v) => println(k))

error: illegal start of simple expression
       map.foreach(case (k, v) => println(k))
                   ^

I can do

> map.foreach(_ match {case (k, v) => println(k)})

1
3

Any better alternatives?

Movable answered 2/6, 2010 at 11:35 Comment(0)
D
45

You were very close with map.foreach(case (k, v) => println(k)). To use case in an anonymous function, surround it by curly brackets.

map foreach { case (k, v) => println(k) }
Dispassion answered 2/6, 2010 at 11:50 Comment(0)
P
12

In such cases I often use the for syntax.

for ((k,v) <- map) println(k)

According to Chapter 23 in "Programming in Scala" the above for loop is translated to call foreach.

Pathy answered 2/6, 2010 at 20:56 Comment(2)
Just a note: one should use a separate flatten if he would want a flatMap with this approach.Mushro
A lot of times it is more functional to use foreach. If you find yourself doing it this way there is probably some abstraction that can be done.Parts
T
5

One alternative is the tupled method of the Function object:

import Function.tupled;
// map tupled foreach {(k, v) => println(k)}
map foreach tupled {(k, v) => println(k)}
Thump answered 2/6, 2010 at 11:54 Comment(4)
@Rahul map foreach Function.tupled((k,v) => println(k)) or map foreach ((k : Int,v : Int) => println(k)).tupled does.Lauro
Yes, sorry I accidently swapped tupled and the function call. I'll change it.Thump
A clever solution. I was unaware of this, and now I learned something. Thanks!Oligarch
Is there a reason one would use this over the accepted answer (Ben Lings)?Parts
B
3

You can also access a tuple as follows:


scala> val map = Map(1 -> 2, 3 -> 4)
map: scala.collection.immutable.Map[Int,Int] = Map((1,2), (3,4))
scala> map foreach (t => println(t._1))
1
3
Buff answered 2/6, 2010 at 11:43 Comment(1)
Yes, forgot to add that alternative. But I don't like it, because in this case the fields of tuple do have actual meaning (key and value) and I want to reflect it in my code.Movable
B
2
Welcome to Scala version 2.8.0.Beta1-prerelease (OpenJDK Server VM, Java 1.6.0_0).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val m = Map('a -> 'b, 'c -> 'd)
m: scala.collection.immutable.Map[Symbol,Symbol] = Map('a -> 'b, 'c -> 'd)

scala> m foreach { case(k, v) => println(k) }
'a
'c
Bushire answered 2/6, 2010 at 11:50 Comment(0)
M
1

I was pretty close with the last attempt, actually:

> map.foreach({case (k, v) => println(k)})
1
3
Movable answered 2/6, 2010 at 11:48 Comment(1)
Note that you don't need the most outer round braces(). Just foreach{case (k,v)=> ???}Mushro

© 2022 - 2024 — McMap. All rights reserved.