了解Scala - >语法

opa*_*isy 2 scala scala-collections scala-2.10

我通过artima" Scala编程 "一书来体验Scala.

在介绍Map特征时,作者会花一些时间将->语法描述为可以应用于任何类型以获取元组的方法.

事实上:

scala> (2->"two")
res1: (Int, String) = (2,two)

scala> (2,"two")
res2: (Int, String) = (2,two)

scala> (2->"two") == (2, "two")
res3: Boolean = true
Run Code Online (Sandbox Code Playgroud)

但那些不等同于:

scala> Map(1->"one") + (2->"two")
res4: scala.collection.immutable.Map[Int,String] = Map(1 -> one, 2 -> two)

scala> Map(1->"one") + (2, "two")
<console>:8: error: type mismatch; 
found   : Int(2)
required: (Int, ?)
             Map(1->"one") + (2, "two")
Run Code Online (Sandbox Code Playgroud)

为什么会如此,因为我的第一次测试似乎表明两个"对"语法都构建了一个元组?

问候.

Rex*_*err 6

它们完全相同,这要归功于这个类Predef(仅在此部分重现):

final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal {
  @inline def -> [B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y)
}
@inline implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x)
Run Code Online (Sandbox Code Playgroud)

所以现在的问题是(a,b)语法何时会变得模棱两可(a -> b)?答案是函数调用,特别是当它们被重载时:

def f[A](a: A) = a.toString
def f[A,B](a: A, b: B) = a.hashCode + b.hashCode
f(1,2)     // Int = 3
f(1 -> 2)  // String = (1,2)
f((1, 2))  // String = (1,2)
Run Code Online (Sandbox Code Playgroud)

地图+特别容易混淆,因为它超载了多参数版本,所以你可以

Map(1 -> 2) + (3 -> 4, 4 -> 5, 5 -> 6)
Run Code Online (Sandbox Code Playgroud)

因此它解释了

Map(1 -> 2) + (3, 4)
Run Code Online (Sandbox Code Playgroud)

尝试将两者都添加3到地图中,然后添加4到地图中.这当然没有意义,但它没有尝试其他解释.

随着->不存在这样的歧义.

但是,你做不到

Map(1 -> 2) + 3 -> 4
Run Code Online (Sandbox Code Playgroud)

因为+-具有相同的优先权.因此它被解释为

(Map(1 -> 2) + 3) -> 4
Run Code Online (Sandbox Code Playgroud)

这又失败了,因为你试图添加3代替键值对.