下列
def mMatch(s: String) = {
var target: String = "a"
s match {
case `target` => println("It was " + target)
case _ => println("It was something else")
}
}
Run Code Online (Sandbox Code Playgroud)
不编译:
错误:需要稳定的标识符,但找到了目标.case
target=> println("它是"+目标)
为什么Scala需要val不是a var.我猜"因为"是一个可以接受的答案,但我觉得我错过了更深层次的原因.
Rex*_*err 41
我怀疑它是为那些可能的情况启用表切换优化(没有成堆检查以查看它是否有效).例如,使用代码
class Sw {
def m(i: Int) = {
val a = 3
val b = 2
val c = 1
i match {
case `a` => 0
case `b` => -1
case `c` => 4
case _ => 2
}
}
}
Run Code Online (Sandbox Code Playgroud)
你得到字节码
public int m(int);
Code:
0: iconst_3
1: istore_2
2: iconst_2
3: istore_3
4: iconst_1
5: istore 4
7: iload_1
8: istore 5
10: iload 5
12: tableswitch{ //1 to 3
1: 48;
2: 44;
3: 52;
default: 40 }
40: iconst_2
41: goto 53
44: iconst_m1
45: goto 53
48: iconst_4
49: goto 53
52: iconst_0
53: ireturn
Run Code Online (Sandbox Code Playgroud)
如果你使用vars会更复杂(你必须检测它们是否已经改变以知道该表表达式是否仍然有效).
Lui*_*hys 13
在匹配中使用它之前,没有什么能阻止你将var变成val:
def mMatch(s: String) = {
var target: String = "a"
val x = target
s match {
case `x` => println("It was " + target)
case _ => println("It was something else")
}
}
Run Code Online (Sandbox Code Playgroud)
工作得非常好.
Kip*_*ros 10
我的猜测是需要稳定的标识符作为简化,以避免变量在匹配自身的模式内发生变化.这需要在规范中加以澄清,并且如Rex Kerr所提到的那样破坏优化.
var x: String = "a"
"b" match {
case `x` if { x = "b"; true } => println("success")
}
Run Code Online (Sandbox Code Playgroud)
编辑.但是这种解释并不完全令人满意,因为稳定的标识符可以指一个可变对象,
val x = collection.mutable.Seq(2)
def f(y: Seq[Int]) {
y match {
case `x` if { x(0) = 3; true } => println("success")
}
}
f(Seq(2)) // success
f(Seq(2)) // failure
Run Code Online (Sandbox Code Playgroud)
注意,稳定的标识符不一定是静态已知的.例如,以下是好的,
def f(x: Int) {
1 match { case `x` => println("hi") }
}
Run Code Online (Sandbox Code Playgroud)