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
^
变量 a
和 res13
的类型都是 Int
但第二种情况与第一种情况不同。
有人可以帮忙吗?
res13
是 val
(定义看起来像 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)
在第一种情况下有效,因为 a
是 var
,因此 a = foo
是合法的,而在第二种情况下,res13
是 val
(代表你的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
我知道 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
^
变量 a
和 res13
的类型都是 Int
但第二种情况与第一种情况不同。
有人可以帮忙吗?
res13
是 val
(定义看起来像 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)
在第一种情况下有效,因为 a
是 var
,因此 a = foo
是合法的,而在第二种情况下,res13
是 val
(代表你的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