问题 Function.tupled和占位符语法


我在另一个中看到了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)。另外我如何使用它来获取弃用警告?


11524
2018-03-01 06:51


起源

@huynhjl对Function.tupled的弃用是理解一个函数必须知道如何在没有帮助的情况下自我元组的结果。但是,对于类型推断,这确实不适用。我确定希望他们不删除Function.tupled而不使类型推理器足够聪明以解决这个问题。 - Daniel C. Sobral
我暂时不推荐它。 - psp


答案:


UPDATE 弃用了 去除 今天,为了回应这个问题。


Tupling函数只是适应 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中,使用`_`和使用命名标识符有什么区别?

UPDATE

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

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。


15
2018-03-01 07:17



谢谢你的回答。令我困惑的是这不起作用: val f = (x:Int, y:String) => x + ": " + y; f.tupled。不应该返回一个适用于(Int,String)元组的f版本吗? - huynhjl
好吧,我知道,这解释了很多。我重新测试了2.8.0.Beta1,它按预期工作。我之前尝试过2.8.0.Beta1-RC5,这是我的路径。我需要摆脱RC5 ...... - huynhjl