为什么scala不能在元组上隐式匹配?

use*_*848 3 scala

你可以在ruby中执行以下操作:

l = [[1, 2], [3, 4], [5, 6]]
m  = l.map {|(a, b)| a+b}
Run Code Online (Sandbox Code Playgroud)

但你不能在scala中执行以下操作:

val a = List((1, 2), (3, 4), (5, 6))

a.map((f, s) => f + s)
<console>:9: error: wrong number of parameters; expected = 1
a.map((f, s) => f + s)
Run Code Online (Sandbox Code Playgroud)

相反,你必须这样做:

a.map { case (f, s) => f + s }
Run Code Online (Sandbox Code Playgroud)

我发现这个相当冗长,因为scala定义了一个"元组"类型,我期待它也能在它之上提供语法糖,以便像上面那样隐式匹配.是否有一些深层原因导致不支持这种匹配?有更优雅的方式吗?

dhg*_*dhg 5

原因

原因是您尝试使用的语法已经具有意义.当高阶函数需要双参数函数时使用它.例如,使用reducefold:

List(1,2,3).reduce((a,b) => a+b)
Run Code Online (Sandbox Code Playgroud)

一个办法

更清洁的方法可以通过定义自己的隐式方法来实现:

import scala.collection.generic.CanBuildFrom
import scala.collection.GenTraversableLike

implicit class EnrichedWithMapt2[A, B, Repr](val
self: GenTraversableLike[(A, B), Repr]) extends AnyVal {
  def mapt[R, That](f: (A, B) => R)(implicit bf: CanBuildFrom[Repr, R, That]) = {
    self.map(x => f(x._1, x._2))
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

val a = List((1, 2), (3, 4), (5, 6))
a.mapt((f, s) => f + s)  // List(3, 7, 11)
Run Code Online (Sandbox Code Playgroud)

其他选择

你可以做一些其他的技巧,比如使用tupled,但它们并没有真正帮助你解决你描述的情况:

val g = (f: Int, s: Int) => f + s
a.map(g.tupled)
Run Code Online (Sandbox Code Playgroud)

要不就

a.map(((f: Int, s: Int) => f + s).tupled)
Run Code Online (Sandbox Code Playgroud)