为什么Scala中的模式匹配不适用于变量?

Hen*_*son 109 scala pattern-matching match

采取以下功能:

def fMatch(s: String) = {
    s match {
        case "a" => println("It was a")
        case _ => println("It was something else")
    }
}
Run Code Online (Sandbox Code Playgroud)

这种模式很好地匹配:

scala> fMatch("a")
It was a

scala> fMatch("b")
It was something else
Run Code Online (Sandbox Code Playgroud)

我希望能做的是以下内容:

def mMatch(s: String) = {
    val target: String = "a"
    s match {
        case target => println("It was" + target)
        case _ => println("It was something else")
        }
}
Run Code Online (Sandbox Code Playgroud)

这会发出以下错误:

fMatch: (s: String)Unit
<console>:12: error: unreachable code
               case _ => println("It was something else")
Run Code Online (Sandbox Code Playgroud)

我想这是因为它认为目标实际上是一个你想分配给输入的名称.两个问题:

  1. 为什么会这样?不能仅在具有适当类型的范围内查找现有变量并首先使用它们,如果没有找到,则将target作为模式匹配的名称处理?

  2. 这有解决方法吗?任何模式匹配变量的方法?最终可以使用大的if语句,但匹配案例更优雅.

Ben*_*mes 207

您正在寻找的是一个稳定的标识符.在Scala中,这些必须以大写字母开头,或者用反引号包围.

这两个都可以解决您的问题:

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

def mMatch2(s: String) = {
    val Target: String = "a"
    s match {
        case Target => println("It was" + Target)
        case _ => println("It was something else")
    }
}
Run Code Online (Sandbox Code Playgroud)

为了避免意外引用封闭范围中已存在的变量,我认为默认行为是将小写模式变为变量而不是稳定标识符.只有当你看到以大写字母或后面的标记开头的东西时,你是否需要知道它来自周围的范围.

  • @Emil实际上,Scala中的大写标识符表示常量.因此,对大写标识符进行模式匹配意味着与常量进行比较.它真的有助于像'Nil`这样的东西,_I_赌是真正的原因. (12认同)
  • 请注意,`target`是一个值(`val`),而不是一个变量(`var`).它不适用于变量. (11认同)
  • 我打赌这来自Erlang,其中变量以大写字母开头,符号以小写字母开头. (3认同)