val map = scala.collection.mutable.Map(1 -> 2)
map(1) += 3
map.apply(1) += 3
(map.apply(1)).+=(3)我不明白为什么代码都编译得很好。
在第一种情况下,我认为代码已经扩展到map(1) = map(1) + 3和map.update(1, map(1) + 3)。但是在第二和第三种情况下,map.apply(1) = map.apply(1) + 3会导致编译错误。
第二和第三段代码是如何扩展到?
发布于 2016-01-18 05:43:42
更新的规则是在指定任务的规范中,以及赋值运算符的扩展。
问题是为什么出于更新规则的目的,显式m.apply不被视为m()。
这两种形式应该是等价物。
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
scala> val map = scala.collection.mutable.Map(1 -> 2)
map: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2)
scala> reify(map(1) += 3)
res0: reflect.runtime.universe.Expr[Unit] = Expr[Unit]($read.map.update(1, $read.map.apply(1).$plus(3)))
scala> reify(map.apply(1) += 3)
res1: reflect.runtime.universe.Expr[Unit] = Expr[Unit]($read.map.update(1, $read.map.apply(1).$plus(3)))
scala> reify(map(1) = map(1) + 3)
res2: reflect.runtime.universe.Expr[Unit] = Expr[Unit]($read.map.update(1, $read.map.apply(1).$plus(3)))
scala> reify(map.apply(1) = map.apply(1) + 3)
<console>:16: error: missing argument list for method apply in trait MapLike
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `apply _` or `apply(_)` instead of `apply`.
reify(map.apply(1) = map.apply(1) + 3)
^
scala> map.apply.update(1, map.apply(1) + 3)
<console>:16: error: missing argument list for method apply in trait MapLike
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `apply _` or `apply(_)` instead of `apply`.
map.apply.update(1, map.apply(1) + 3)
^编辑: FWIW,事情就是这样的。
编辑:
这是异常现象:
scala> val m = collection.mutable.Map(1->2)
m: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2)
scala> m(1) = m(1) + 3
scala> m(1) += 3
scala> m.apply(1) += 3
scala> m.apply(1) = m.apply(1) + 3
<console>:13: error: missing argument list for method apply in trait MapLike
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `apply _` or `apply(_)` instead of `apply`.
m.apply(1) = m.apply(1) + 3
^由于这些表达式都是等价的,所以它们都应该编译为对update的调用。
最后一个表达式无法键入类型,因为编译器对m.apply.update(1, m.apply(1) + 3)进行机械重写,而不是m.update。
在gitter聊天中的解释是,在这种情况下,编译器不需要足够聪明地将m.apply(1)识别为m(1)。毕竟,可能会出现模棱两可的情况。如果apply是无参数的,并且使用update方法返回一个值,该怎么办?如果m.apply(1)不是打字机的话,你会把它当作m(1)吗?
很明显,根据规范,m(1) += ???被扩展为m(1) = m(1) + ???,然后转换为m.update(1, m(1) + ???)。
在代码中,压缩了两个转换(将op=转换为x = x op expr,将x(1) = ???转换为x.update(1, ???)):
转换为更新 (或普通赋值)。
可能可以绕过实现中的限制,但并不明显的是它会很好地规范(如上面所示,其中apply可能是无参数的)。
那么,为了对称性,m.apply(1) += 3应该不能编译吗?如果编译器更努力地保留源表达式,那么在这种情况下它至少会更一致。
发布于 2016-01-18 18:05:50
FWIW,这适用于2.12.0-M3
C:\Users\erichardson>scala
Welcome to Scala 2.12.0-M3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_66).
Type in expressions for evaluation. Or try :help.
scala> val map = scala.collection.mutable.Map(1 -> 2)
map: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2)
scala> map(1) += 3
scala> map
res1: scala.collection.mutable.Map[Int,Int] = Map(1 -> 5)
scala> map.apply(1) += 3
scala> map
res3: scala.collection.mutable.Map[Int,Int] = Map(1 -> 8)
scala> (map.apply(1)).+=(3)
scala> map
res5: scala.collection.mutable.Map[Int,Int] = Map(1 -> 11)
scala>https://stackoverflow.com/questions/34847377
复制相似问题