Question

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?

Était-ce utile?

La solution

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.

Autres conseils

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top