5

如果我做:

val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map { t => t._1 + t._2 }

没关系。

如果我做:

val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map { case (b, n) => b + n }

也没关系。

但如果我这样做:

val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map { (b, n) => b + n }

不起作用。
为什么要使用“case”关键字来使用命名元组?

4

3 回答 3

8

2.11 的错误信息更能说明问题:

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 }
                          ^

对于应用程序,您将获得“自动元组”:

scala> def f(p: (Int, Int)) = p._1 + p._2
f: (p: (Int, Int))Int

scala> f(1,2)
res0: Int = 3

您提供了两个 args 而不是一个。

但是你不会得到自动解耦。

人们一直希望它以这种方式工作

于 2014-04-08T17:54:15.837 回答
1

这种情况可以用types内部函数来理解。

首先,函数的参数函数类型语法map如下。

Tuple2[Int,Int] => B //Function1[Tuple2[Int, Int], B]

第一个参数函数扩展为this。

(t:(Int,Int)) => t._1 + t._2 // type : Tuple2[Int,Int] => Int

还行吧。然后是第二个功能。

(t:(Int, Int)) => t match {
  case (a:Int, b:Int) => a + b
}

这也可以。在失败场景中,

(a:Int, b:Int) => a + b 

让我们检查函数的类型

(Int, Int) => Int // Function2[Int, Int, Int]

所以参数函数类型是错误的。

作为一种解决方案,您可以使用 Function 对象中的辅助函数将多个 arity 函数转换为元组模式并向后转换。您可以执行以下操作。

val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
l map(Function.tupled((b, n) => b + n ))

请参阅函数 API以获取更多信息。

于 2014-04-08T18:27:44.250 回答
0

传递给应用于序列的映射函数的函数参数的类型由序列中元素的类型推断。尤其是,

场景1:l map { t => t._1 + t._2 }相同l map { t: ((String, String)): (String) => t._1 + t._2 }但更短,这是可能的,因为类型推断。Scala 编译器自动推断参数的类型为(String, String) => String

场景2:你也可以写更长的形式

l map { t => t match {
    case(b, n) => b + n
  }
}

场景3:将错误类型的函数传递给map,类似于

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
于 2014-04-08T20:59:12.577 回答