If I do:
val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map { t => t._1 + t._2 }
It's ok.
If I do:
val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map { case (b, n) => b + n }
It's ok too.
But if I do:
val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map { (b, n) => b + n }
It will not work.
Why should I use "case" keyword to use named tuples?
The error message with 2.11 is more explanatory:
scala> l map { (b, n) => b + n }
<console>:9: error: missing parameter type
Note: The expected type requires a one-argument function accepting a 2-Tuple.
Consider a pattern matching anonymous function, `{ case (b, n) => ... }`
l map { (b, n) => b + n }
^
<console>:9: error: missing parameter type
l map { (b, n) => b + n }
^
For an apply, you get "auto-tupling":
scala> def f(p: (Int, Int)) = p._1 + p._2
f: (p: (Int, Int))Int
scala> f(1,2)
res0: Int = 3
where you supplied two args instead of one.
But you don't get auto-untupling.
People have always wanted it to work that way.
This situation can be understand with the types
of inner function.
First, the type syntax of parameter function for the map
function is as follows.
Tuple2[Int,Int] => B //Function1[Tuple2[Int, Int], B]
The first parameter function is expand to this.
(t:(Int,Int)) => t._1 + t._2 // type : Tuple2[Int,Int] => Int
This is ok. Then the second function.
(t:(Int, Int)) => t match {
case (a:Int, b:Int) => a + b
}
This is also ok. In the failure scenario,
(a:Int, b:Int) => a + b
Lets check the types of the function
(Int, Int) => Int // Function2[Int, Int, Int]
So the parameter function type is wrong.
As a solution, you can convert multiple arity functions to tuple mode and backward with the helper functions in Function object. You can do following.
val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map(Function.tupled((b, n) => b + n ))
Please refer Function API for further information.
The type of a function argument passed to map function applied to a sequence is inferred by the type of elements in the sequence. In particular,
scenario 1: l map { t => t._1 + t._2 }
is same as l map { t: ((String, String)): (String) => t._1 + t._2 }
but shorter, which is possible because of type inference. Scala compiler automatically inferred the type of the argument to be (String, String) => String
scenario 2: you can also write in longer form
l map { t => t match {
case(b, n) => b + n
}
}
scenario 3: a function of wrong type is passed to map, which is similar to
def f1 (a: String, b: String) = a + b
def f2 (t: (String, String)) = t match { case (a, b) => a + b }
l map f1 // won't work
l map f2