Using Tuples in map, flatmap,… partial functions

别等时光非礼了梦想. 提交于 2019-11-29 14:55:01

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!