【问题标题】:Using Tuples in map, flatmap,... partial functions在 map、flatmap、...偏函数中使用元组
【发布时间】:2014-04-08 17:44:43
【问题描述】:

如果我这样做:

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”关键字来使用命名元组?

【问题讨论】:

标签: scala tuples partialfunction


【解决方案1】:

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

你提供了两个参数而不是一个。

但您不会自动取消配对。

人们有always wanted it to work that way

【讨论】:

    【解决方案2】:

    这种情况可以用内部函数的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 ))
    

    请参考Function API了解更多信息。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-07
        • 2019-03-11
        • 2014-02-04
        • 2021-11-18
        • 1970-01-01
        • 2019-08-27
        相关资源
        最近更新 更多