Scala模式与小写变量名匹配

时间:2010-12-18 18:42:32

标签: scala scala-2.8

我发现当使用模式匹配替代(对于字符串)时,Scala接受以大写字母开头的变量(在下面的例子中,MyValue1MyValue2),但不是以小写字母开头的变量(myValue1myValue2)。这是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")
}

在跑步时,我得到以下内容:

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")
                     ^

修改

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

当我使用时:

x match {
   case myValue1 => println ("match")
   case _ => 
}

我在最后一个案例中收到unreachable code警告,暗示第一个案件始终匹配。

4 个答案:

答案 0 :(得分:37)

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

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

x match {
   case MyValue1 | MyValue2 => println ("first match")
   case y | z => println ("second match")
}

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

x match {
   case MyValue1 | MyValue2 => println ("first match")
   case `myValue1` | `myValue2` => println ("second match")
}

答案 1 :(得分:8)

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

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

x match {
   case myValue1 => println ("match")
   case _ => 
}

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

x match {
   case MyValue1 => println("match")
   case MyValue2 => println("match")
   case other    => println("no match: "+other)
}

当然,可以使用上面的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 =>
}

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

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

答案 2 :(得分: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

答案 3 :(得分:2)

如果有帮助,我只是在@ http://asoftsea.tumblr.com/post/2102257493/magic-match-sticks-and-burnt-fingers

一周左右发表了一篇关于这个主题的文章