首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这段代码能工作:"map.apply(1)+=3“

为什么这段代码能工作:"map.apply(1)+=3“
EN

Stack Overflow用户
提问于 2016-01-18 04:32:57
回答 2查看 2.1K关注 0票数 2
代码语言:javascript
复制
val map = scala.collection.mutable.Map(1 -> 2)

map(1) += 3
map.apply(1) += 3
(map.apply(1)).+=(3)

我不明白为什么代码都编译得很好。

在第一种情况下,我认为代码已经扩展到map(1) = map(1) + 3map.update(1, map(1) + 3)。但是在第二和第三种情况下,map.apply(1) = map.apply(1) + 3会导致编译错误。

第二和第三段代码是如何扩展到?

EN

回答 2

Stack Overflow用户

发布于 2016-01-18 05:43:42

更新的规则是在指定任务的规范中,以及赋值运算符的扩展。

问题是为什么出于更新规则的目的,显式m.apply不被视为m()

这两种形式应该是等价物

有人只是用争论不休更新示例语法。

代码语言:javascript
复制
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,事情就是这样的

编辑:

这是异常现象:

代码语言:javascript
复制
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, ???)):

决定某事物是否是可变的

关于op=错误,尝试转换为赋值

转换为更新 (或普通赋值)。

可能可以绕过实现中的限制,但并不明显的是它会很好地规范(如上面所示,其中apply可能是无参数的)。

那么,为了对称性,m.apply(1) += 3应该不能编译吗?如果编译器更努力地保留源表达式,那么在这种情况下它至少会更一致。

票数 2
EN

Stack Overflow用户

发布于 2016-01-18 18:05:50

FWIW,这适用于2.12.0-M3

代码语言:javascript
复制
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>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34847377

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档