Scala模式与小写变量名匹配

Jus*_*s12 14 scala scala-2.8

我发现当使用模式匹配替代(对于字符串)时,Scala接受以大写字母开头的变量(在下面的示例中,MyValue1MyValue2),但不接受以小写字母(myValue1,myValue2)开头的变量.这是Scala的错误还是功能?我在2.8版本中得到了这个.如果这是一个功能,任何人都可以解释其背后的基本原理吗?这是我使用的代码:

val myValue1 = "hello"
val myValue2 = "world"
val MyValue1 = "hello"
val MyValue2 = "world"

var x:String = "test"

x match {
  case MyValue1 | MyValue2 => println ("first match")
  case myValue1 | myValue2 => println ("second match")
}
Run Code Online (Sandbox Code Playgroud)

在运行时,我得到以下内容:

scala> val myValue1 = "hello"
myValue1: java.lang.String = hello

scala> val myValue2 = "world"
myValue2: java.lang.String = world

scala> val MyValue1 = "hello"
MyValue1: java.lang.String = hello

scala> val MyValue2 = "world"
MyValue2: java.lang.String = world

scala> var x:String = "test"
x: String = test

scala> x match {
 |   case MyValue1 | MyValue2 => println ("first match")
 |   case myValue1 | myValue2 => println ("second match")
 | }
<console>:11: error: illegal variable in pattern alternative
     case myValue1 | myValue2 => println ("second match")
          ^
<console>:11: error: illegal variable in pattern alternative
     case myValue1 | myValue2 => println ("second match")
                     ^
Run Code Online (Sandbox Code Playgroud)

编辑:

所以它确实是一个功能,而不是一个错误...任何人都可以提供一个例子,这可能有用吗?

我用的时候:

x match {
   case myValue1 => println ("match")
   case _ => 
}
Run Code Online (Sandbox Code Playgroud)

我收到了unreachable code关于最后一个案例的警告,暗示第一个案件始终匹配.

Aar*_*rup 37

这不是特定于具有替代品的模式,并且它不是错误.在模式中以小写字母开头的标识符表示在模式匹配时将绑定的新变量.

所以,你的例子相当于写作:

x match {
   case MyValue1 | MyValue2 => println ("first match")
   case y | z => println ("second match")
}
Run Code Online (Sandbox Code Playgroud)

您可以使用反引号解决此问题:

x match {
   case MyValue1 | MyValue2 => println ("first match")
   case `myValue1` | `myValue2` => println ("second match")
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*ral 8

这是一个功能.以大写字母开头的稳定标识符被视为文字以用于模式匹配,而小写标识符被"分配",因此您可以将匹配的值用于其他内容.

你给出了一个没有意义的例子:

x match {
   case myValue1 => println ("match")
   case _ => 
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我们稍微改变一下,这种感觉很容易看出来:

x match {
   case MyValue1 => println("match")
   case MyValue2 => println("match")
   case other    => println("no match: "+other)
}
Run Code Online (Sandbox Code Playgroud)

当然,可以使用x而不是other上面,但这里有一些不方便的例子:

(pattern findFirstIn text) {
    // "group1" and "group2" have been extracted, so were not available before
    case pattern(group1, group2) =>

    // "other" is the result of an expression, which you'd have to repeat otherwise
    case other =>
}

getAny match {
    // Here "s" is a already a string, whereas "getAny" would have to be typecast
    case s: String =>

    // Here "i" is a already an int, whereas "getAny" would have to be typecase
    case i: Int =>
}
Run Code Online (Sandbox Code Playgroud)

因此,为方便模式匹配将匹配的值分配给标识符有很多原因.

现在,虽然我认为这是Scala最大的错误之一,因为它是如此微妙和独特,其背后的推理是,在推荐的Scala风格中,常量是以大写字母开头的驼峰,而方法和vals和vars(也是真正的方法)是以小写字母开头的驼峰.因此常量被自然地视为文字,而其他常量被视为可分配标识符(可以影响在外部上下文中定义的标识符).


mpi*_*ist 5

这里发生的是myValue1和myValue2被视为变量标识符(即,绑定到匹配值的新变量的定义),而MyValue1和MyValue2被视为引用先前声明的值的稳定标识符.在模式匹配的情况下,变量标识符必须以小写字母开头,因此第一种情况的行为直观.有关详细信息,请参阅Scala语言规范的第8.1节(http://www.scala-lang.org/docu/files/ScalaReference.pdf).

稍微改变您的示例,您可以看到变量标识符:

scala> x match {
 | case MyValue1 | MyValue2 => println ("first match")
 | case myValue1 => println (myValue1)
 | }
test
Run Code Online (Sandbox Code Playgroud)