2010-12-18 2 views
13

대안 (문자열)에 대한 패턴 매칭을 사용할 때 스칼라는 대문자 (다음 예제에서는 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") 
} 

, 나는 다음과 같은 얻을 :

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

@이 스칼라에서 일반적인 프로그래밍 실수 중 하나입니다 http://stackoverflow.com/questions/1332574/common- 프로그래밍 실수 - 스칼라 개발자 - 투 - 피/2489355 # 2489355. 전체 스레드를 읽는 것이 좋습니다.이 스레드는 다른 스레드와 비슷합니다. – Steve

+0

좋은 참고를 보내 주셔서 감사합니다. – Jus12

+0

유용한 예 :'x match {case myValue1 : String => println ("match :"+ myValue1); case _ =>}'-> myValue1은 지역 변수가됩니다. – Madoc

답변

33

이 대안과 패턴에 국한되지이며, 그것은 버그가 아닙니다 :

약간 예를 변경하면, 당신은 변수 식별자를 볼 수 있습니다. 패턴에서 소문자로 시작하는 식별자는 패턴이 일치 할 경우 바인딩 될 새 변수를 나타냅니다.

그래서, 당신의 예를 작성하는 것과 같습니다

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

이것은 매우 미묘한 기능이며 많은 사람들이 버그라고 생각할 것입니다. 해결 방법을 제공 할 답변으로 선택되었습니다. – Jus12

5

여기서 일어나는 일은 myValue1과 myValue2가 변수 식별자 (즉, 일치하는 값에 바인딩 된 새 변수의 정의)로 처리되는 반면 MyValue1과 MyValue2는 선언 된 값을 참조하는 안정된 식별자로 처리된다는 것입니다 일찍이. 패턴 일치의 경우, 변수 식별자는 소문자로 시작해야하며, 따라서 첫 번째 경우는 직관적으로 동작합니다. 정확한 세부 사항은 스칼라 언어 규격 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 
+0

참고해 주셔서 감사합니다. 정확한 섹션은 8.1.1입니다. 나는 하나의 정답만을 선택할 수 있었다. – Jus12

6

그것은 기능입니다. 대문자로 시작하는 안정적인 식별자는 패턴 일치를 위해 리터럴처럼 취급되며 소문자 식별자는 "할당 됨"이므로 다른 값에 대해 일치 된 값을 사용할 수 있습니다.

당신은 이해하고 있지 그것의 예를 주었다

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

일치하는 값을 식별자에 할당하는 것이 패턴 일치에 편리한 이유는 여러 가지가 있습니다.

스칼라의 가장 큰 오판 중 하나라고 생각하지만, 너무 미묘하고 독특하기 때문에 스칼라에서 권장하는 스칼라 스타일에서는 대문자로 시작하는 상수가 낙타로되어 있습니다. 메소드와 val과 vars (실제로 메소드도 있음)는 소문자로 시작하는 낙타 사례입니다. 따라서 상수는 자연스럽게 리터럴로 취급되는 반면, 다른 것은 할당 가능한 식별자로 처리됩니다 (외부 컨텍스트에 정의 된 식별자를 섀도 잉 할 수 있음). 도움이된다면

관련 문제