post 和 pre increment 对于 scala 中的 REPL 变量没有按预期工作

post and pre increment not working as expected for REPL variable in scala

我知道 scala 中没有 ++-- 而我必须使用 +=-=

但是当我尝试

scala> var a=2
a: Int = 2

scala> a +=1

scala> a
res11: Int = 3

上面的工作正常但下面的不行

scala> 5
res13: Int = 5

scala> res13 +=1
<console>:9: error: value += is not a member of Int
              res13 +=1
                    ^

变量 ares13 的类型都是 Int 但第二种情况与第一种情况不同。

有人可以帮忙吗?

res13val(定义看起来像 val res13 = 5),而不是 var。 Vals 是 "values",它们不能被修改,所以像 +=-= 这样的运算符不能与它们一起工作。

快速回答:您将 a 声明为 var,这意味着它的值可以更改。另一方面,REPL res<x> 是只读的 val,因此无法更改。

现在,查看错误消息。在 Scala 中,Int 在语言层面并不特殊,运算符也不特殊。所以 a += 1 表示 a.+=(1) 其中 += 是方法名称。事实上,Int 上没有 += 方法,这是您收到的错误消息。但是当运算符名称以“=”结尾而找不到时,IF接收者是一个var,那么编译器会将a op= b转化为a = a op b.所以在第一种情况下,a += 1 变成了 a = a + 1。这是有效的,因为 + 当然在 Int 上可用,但在第二种情况下不可用。

错误消息有点误导。它可能应该说没有 += 成员,但是,因为有一个 + 成员,它也应该说 res13 不能分配给。

ω=这样的运算符的脱糖,其中ω是一串运算符字符,与其他运算符有点不同。

a foo b

等同于

a.foo(b)

的情况下
a ω= b

这只相当于

a.ω=(b)

如果它进行类型检查,否则,编译器也会尝试

a = a ω b

(加上 a 保证只计算一次的条款)即

a = a.ω(b)

this.a_=(a.ω(b))

因此,在您的情况下,由于 Int 是不可变的,并且没有 Int.+= 方法,代码实际上将脱糖为

a = a.+(1) // *not* a.+=(1)

res13 = res13.+(1) // *not* res13.+=(1)

在第一种情况下有效,因为 avar,因此 a = foo 是合法的,而在第二种情况下,res13val(代表你的REPL session的第13次求值结果,突然变非常奇怪!)所以赋值是不合法的。

回答有关您可以从控制台显示的内容的问题:

你可以使用魔法后缀// show看看生成了什么

事后,您可以获得标识符的符号和类型,包括用户定义的和合成的。

scala> 42 // show
object $read extends scala.AnyRef {
  def <init>() = {
    super.<init>;
    ()
  };
  object $iw extends scala.AnyRef {
    def <init>() = {
      super.<init>;
      ()
    };
    object $iw extends scala.AnyRef {
      def <init>() = {
        super.<init>;
        ()
      };
      val res0 = 42
    }
  }
}
res0: Int = 42

scala> $intp.symbolOfIdent("res0").owner.typeSignature
res1: $intp.global.Type =
Object {
  def <init>(): type
  val res0(): Int
  private[this] val res0: Int
}

这显示了基础字段和访问器。与 var 比较:

scala> var a = 7
a: Int = 7

scala> $intp.symbolOfIdent("a").owner.typeSignature
res4: $intp.global.Type =
Object {
  def <init>(): type
  def a(): Int
  def a_=(x: Int): Unit
  private[this] var a: Int
}

还有其他可用的 API 例如

$intp.typeOfTerm("res0").resultType.typeSymbol.typeSignature

scala> val m = collection.mutable.Map(1->2)
m: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2)

scala> $intp.typeOfTerm("m").resultType member $intp.global.TermName("+=").encodedName
res7: $intp.global.Symbol = value +=

哪里

scala> $intp.global.TermName("+=").encodedName
res8: $intp.global.TermName = $plus$eq