21

In scala foreach loop if I have list

val a = List("a","b","c","d")

I can print them without a pattern matching like this

a.foreach(c => println(c))

But, if I have a tuple like this

val v = Vector((1,9), (2,8), (3,7), (4,6), (5,5))

why should I have to use

v.foreach{ case(i,j) => println(i, j) }
  1. a pattern matching case
  2. { brackets

Please explain what happens when the two foreach loops are executed.

Srinivas
  • 2,010
  • 7
  • 26
  • 51
  • It is design flaw in scala. There is probably explanation for this, but it will be long and mainly useless. – talex Jul 18 '17 at 12:50
  • According to the Dotty team in Scala 3 this will be valid: `v.foreach((i,j) => println(i, j))` – kanbagoly Jul 18 '17 at 22:27

4 Answers4

17

You don't have to, you choose to. The problem is that the current Scala compiler doesn't deconstruct tuples, you can do:

v.foreach(tup => println(tup._1, tup._2))

But, if you want to be able to refer to each element on it's own with a fresh variable name, you have to resort to a partial function with pattern matching which can deconstruct the tuple.

This is what the compiler does when you use case like that:

def main(args: Array[String]): Unit = {
  val v: List[(Int, Int)] = scala.collection.immutable.List.apply[(Int, Int)](scala.Tuple2.apply[Int, Int](1, 2), scala.Tuple2.apply[Int, Int](2, 3));
  v.foreach[Unit](((x0$1: (Int, Int)) => x0$1 match {
    case (_1: Int, _2: Int)(Int, Int)((i @ _), (j @ _)) => scala.Predef.println(scala.Tuple2.apply[Int, Int](i, j))
  }))
}

You see that it pattern matches on unnamed x0$1 and puts _1 and _2 inside i and j, respectively.

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
6

According to http://alvinalexander.com/scala/iterating-scala-lists-foreach-for-comprehension:

val names = Vector("Bob", "Fred", "Joe", "Julia", "Kim")

for (name <- names)
    println(name)
Melebius
  • 6,183
  • 4
  • 39
  • 52
grnc
  • 477
  • 6
  • 13
2

To answer #2: You can only use case in braces. A more complete answer about braces is located here.

pJunger
  • 41
  • 6
1

Vector is working a bit differently, you using function literals using case...

In Scala, we using brackets{} which accept case...

{
  case pattern1 => "xxx"
  case pattern2 => "yyy"
}

So, in this case, we using it with foreach loop...

Print all values using the below pattern then:

val nums = Vector((1,9), (2,8), (3,7), (4,6), (5,5))

nums.foreach {
    case(key, value) => println(s"key: $key, value: $value")
}

Also you can check other loops like for loop as well if you think this is not something which you are comfortable with...

Alireza
  • 100,211
  • 27
  • 269
  • 172