11

我在另一个答案中看到了 Function.tupled 示例的这种用法:Map(1 -> "one", 2 -> "two") map Function.tupled(_ -> _.length)

有用:

scala> Map(1 -> "one", 2 -> "two") map Function.tupled(_ -> _.length)
<console>:5: warning: method tupled in object Function is deprecated: 
Use `f.tuple` instead
       Map(1 -> "one", 2 -> "two") map Function.tupled(_ -> _.length)
                                                ^
res0: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3)

如果我不想使用占位符语法,似乎可以不用。

scala> Map(1 -> "one", 2 -> "two") map (x => x._1 -> x._2.length)
res1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3)

直接使用占位符语法不起作用:

scala> Map(1 -> "one", 2 -> "two") map (_._1 -> _._2.length)
<console>:5: error: wrong number of parameters; expected = 1
       Map(1 -> "one", 2 -> "two") map (_._1 -> _._2.length)

Function.tupled 是如何工作的?中似乎发生了很多事情Function.tupled(_ -> _.length)。另外,我将如何使用它来不收到弃用警告?

4

1 回答 1

15

更新为了解决这个问题,今天删除了 弃用。


对函数进行元组化只是为了FunctionN[A1, A2, ..., AN, R]适应Function1[(A1, A2, ..., AN), R]

Function.tuple已弃用,取而代之的是FunctionN#tupled. 一个(可能是意外的)后果是类型推断器无法推断以下参数类型:

scala> Map(1 -> "one", 2 -> "two") map (_ -> _.length).tupled                 
<console>:5: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$minus$greater(x$2.length))
       Map(1 -> "one", 2 -> "two") map (_ -> _.length).tupled
                                        ^
<console>:5: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$minus$greater(x$2.length))
       Map(1 -> "one", 2 -> "two") map (_ -> _.length).tupled

这些中的任何一个都可以:

scala> Map(1 -> "one", 2 -> "two") map { case (a, b)  => a -> b.length }
res8: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3)

scala> Map(1 -> "one", 2 -> "two") map ((_: Int) -> (_: String).length).tupled           
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3)

scala> Map(1 -> "one", 2 -> "two") map ((p: (Int, String))  => p._1 -> p._2.length)
res12: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 3)

我建议您阅读这个最近的问题的答案,以更深入地了解函数文字中的 '_',以及类型推断的工作原理:

在 Scala 中,使用 `_` 和使用命名标识符有什么区别?

更新

在回答评论时,确实如此。

scala> val f = (x:Int, y:String) => x + ": " + y
f: (Int, String) => java.lang.String = <function2>

scala> f.tupled
res0: ((Int, String)) => java.lang.String = <function1>

scala> Map(1 -> "1") map f.tupled
res1: scala.collection.immutable.Iterable[java.lang.String] = List(1: 1)

这需要 Scala 2.8。请注意,如果函数的返回类型为 a ,则 Map#map 可能会导致另一个映射,Tuple2否则为 List,如上所述。

于 2010-03-01T07:17:20.787 回答