scala 为什么变量不能是稳定的标识符?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7083502/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:21:10  来源:igfitidea点击:

Why can't a variable be a stable identifier?

scala

提问by Malvolio

The following

下列

def mMatch(s: String) = {
    var target: String = "a"
    s match {
        case `target` => println("It was " + target)
        case _ => println("It was something else")
    }
}

does not compile:

不编译:

error: stable identifier required, but target found. case target=> println("It was " + target)

错误:需要稳定的标识符,但找到了目标。case target=> println("这是" + target)

Why does Scala require a valnot a var. I guess "Because" would be an acceptable answer but I have the feeling there is a deeper reason I am missing.

为什么 Scala 需要一个val不是var. 我想“因为”将是一个可以接受的答案,但我觉得我错过了更深层次的原因。

回答by Rex Kerr

I suspect that it's to enable table-switching optimizations for those cases where it is possible (without piles of checking to see whether it's valid). For example, with the code

我怀疑它是在可能的情况下启用表切换优化(无需大量检查以查看它是否有效)。例如,使用代码

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
    }
  }
}

you get the bytecode

你得到字节码

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

which would be much more complicated to do if you used vars (you'd have to detect whether they had changed to know whether that table expression was still valid).

如果您使用 vars(您必须检测它们是否已更改以了解该表表达式是否仍然有效),这将变得更加复杂。

回答by Luigi Plinge

There's nothing to stop you just turning your var into a val before using it in the match:

没有什么可以阻止您在比赛中使用 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")
    }
}

works perfectly fine.

工作得很好。

回答by Kipton Barros

My guess is stable identifiers are required as a simplification to avoid situations where the variable changes inside the pattern matching itself. This would require clarification in the spec, and disrupt optimizations as Rex Kerr mentions.

我的猜测是需要稳定的标识符作为一种简化,以避免在模式匹配本身内发生变量变化的情况。这需要在规范中进行澄清,并会像 Rex Kerr 提到的那样破坏优化。

var x: String = "a"
"b" match {
  case `x` if { x = "b"; true } => println("success")
}

Edit.But this explanation is not completely satisfactory, because the stable identifier could refer to a mutable object,

编辑。但是这种解释并不完全令人满意,因为稳定标识符可以引用可变对象,

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

Note that a stable identifier is not necessarily known statically. For example, the following is fine,

请注意,稳定标识符不一定是静态已知的。例如,以下内容很好,

def f(x: Int) {
  1 match { case `x` => println("hi") }
}