我注意到 Scala 中的这种行为
val list = List[(Int, Int)]()
val set = HashSet[(Int, Int)]()
scala> list :+ (1, 2)
res30: List[(Int, Int)] = List((1,2))
scala> list :+ (1 -> 2)
res31: List[(Int, Int)] = List((1,2))
scala> list :+ 1 -> 2
res32: List[(Int, Int)] = List((1,2))
//Work
// But the same for set not work
set += (1, 2)
<console>:14: error: type mismatch;
found : Int(2)
required: (Int, Int)
set += (1, 2)
//Ok may be += in set mean add all that mean this should work
set += ((1, 2))
set += ((1, 2), (3,4))
// Worked
// But why this one work
set += 1 -> 2
set += (1 -> 2)
set += ((1 -> 2))
Run Code Online (Sandbox Code Playgroud)
现在我很困惑,你能解释一下为什么元组不是元组吗?
scala> (4->5).getClass
res28: Class[_ <: (Int, Int)] = class scala.Tuple2
scala> (4,7).getClass
res29: Class[_ <: (Int, Int)] = class scala.Tuple2$mcII$sp
Run Code Online (Sandbox Code Playgroud)
我认为区别在于为HashSet[T]定义了两个重载+=,其中一个采用单个T,另一个采用多个(作为T*参数列表)。这是从 继承的Growable[T],并在此处显示。
List[T].:+只能T在右手边取一个,这就是为什么编译器会发现它正在查看一个元组,而不是应该变成参数列表的东西。
如果你这样做,set += ((1, 2))它就会编译。还,val tuple = (1,2); set += x也有效。
请参阅 Mario Galic 的回答,了解为什么在HashSet[T].+=编译器的情况下选择无法输入的重载而不是可以输入的重载。
解析器阶段-Xprint:parser给出
set.$plus$eq(1, 2)
Run Code Online (Sandbox Code Playgroud)
这似乎解决了
def += (elem1: A, elem2: A, elems: A*)
Run Code Online (Sandbox Code Playgroud)
这是一种接受多个参数的方法,因此编译器可能会认为elem1 = 1或elem2 = 2而不是将其视为(1,2)元组。
missingfaktor指向SLS 6.12.3 中缀操作作为解释
左关联运算符的右手操作数可能由括在括号中的几个参数组成,例如;op;(1,...,)。然后这个表达式被解释为 .op(1,...,)。
现在运算符+=是左结合的,因为它不以 结尾:,并且右边的操作数+=由括在括号 中的几个参数组成(1,2)。因此,通过设计,编译器不治疗(1,2)的Tuple2。
| 归档时间: |
|
| 查看次数: |
44 次 |
| 最近记录: |