【问题标题】:Scala pattern matching with lowercase variable nameScala模式匹配小写变量名
【发布时间】:2011-05-27 15:22:05
【问题描述】:

我发现当使用模式匹配和替代(字符串)时,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 警告,暗示第一种情况总是匹配的。

【问题讨论】:

  • 这是 Scala 中常见的编程错误之一:stackoverflow.com/questions/1332574/…。我强烈建议阅读整个线程 - 它还有很多其他类似的问题。
  • 感谢您的精彩参考。
  • 一个有用的例子:x match { case myValue1:String =&gt; println("match: "+myValue1) ; case _ =&gt; } --> myValue1 变成一个局部变量。
  • “伟大的线程”-> 课程 SO 出于“适度的原因”将其删除。 +1 迂腐,-1 实用性。

标签: scala scala-2.8


【解决方案1】:

如果有帮助的话,我一周左右就在这个话题上发了一篇文章@http://asoftsea.tumblr.com/post/2102257493/magic-match-sticks-and-burnt-fingers

【讨论】:

    【解决方案2】:

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

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

    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 (它们也是真正的方法)以小写字母开头的驼峰式大小写。因此,常量自然地被视为文字,而其他常量则被视为可分配的标识符(可能会影响在外部上下文中定义的标识符)。

    【讨论】:

      【解决方案3】:

      这不是特定于具有替代方案的模式,也不是错误。模式中以小写字母开头的标识符表示一个新变量,如果模式匹配,该变量将被绑定。

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

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

      【讨论】:

      • 这是一个非常微妙的功能,很多人可能会认为这是一个错误。选择作为解决方法的答案。
      【解决方案4】:

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

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

      scala> x match {
       | case MyValue1 | MyValue2 => println ("first match")
       | case myValue1 => println (myValue1)
       | }
      test
      

      【讨论】:

      • 感谢您的参考。确切的部分是 8.1.1。我只能选择一个正确的答案。
      猜你喜欢
      • 1970-01-01
      • 2019-11-25
      • 2016-05-17
      • 2021-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-15
      相关资源
      最近更新 更多