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.