Using Tuples in map, flatmap,… partial functions

倖福魔咒の 提交于 2019-12-29 09:04:10

问题


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?


回答1:


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.




回答2:


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.




回答3:


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


来源:https://stackoverflow.com/questions/22944468/using-tuples-in-map-flatmap-partial-functions

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