2016-09-21 4 views
2

, 위의 코드에서::에 대한 패턴 매칭은 어떻게 구현됩니까? 예를 들어

List(1, 2, 3) match { 
    case x :: y => (x, y) 
} 

는 패턴 매칭은 자동으로 비어 있지 않은 List이 경우 x :: y 일치하는 것을 발견 할 것이다. 나는 이것이 왜 발생 하는지를 알고 싶다.

우리 모두가 알다시피, List 클래스에는 :: 방법이 있습니다. 또한, 나는 :: 경우 클래스는 "list.scala"에있다 찾을 :

/** A non empty list characterized by a head and a tail. 
* @param head the first element of the list 
* @param tl the list containing the remaining elements of this list after the first one. 
* @tparam B the type of the list elements. 
* @author Martin Odersky 
* @version 1.0, 15/07/2003 
* @since 2.8 
*/ 
@SerialVersionUID(509929039250432923L) // value computed by serialver for 2.11.2, annotation added in 2.11.4 
final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] { 
    override def tail : List[B] = tl 
    override def isEmpty: Boolean = false 
} 

따라서, 우리는 ::(1, Nil) 새로운 List을 구성 작성할 수 있습니다. 무엇 스칼라에서 중위 표기법으로, 우리는 동등하게 1 :: Nil을 쓸 수 있습니다, 더 (이 Nil.::(1) 어쩌면 약간의 우선 순위 규칙으로 인해보다는 ::(1, Nil)를 호출됩니다 것을 알 수 있습니다.) 그 결과

, 나는 추측 case 클래스 ::::의 패턴 일치와 관련이 있습니다 (예 : x :: y::.unapply과 일치합니다). 그러나 케이스 클래스 ::에 대한 unapply 메소드 또는 컴패니언 객체를 찾지 못했습니다.

아무도 내 추측이 맞는지 말해 줄 수 없습니까? 그렇지 않다면, ::에 대한 패턴 일치가 스칼라에서 어떻게 구현됩니까?

감사합니다.

은 편집 :

물론, :: 같은 경우 클래스가하는 ::.unapply 자동 :: 생성됩니다. 따라서 나는 이 :: (예 : :((1,2))의 인스턴스와 일치 함을 이해할 수 있습니다. 그러나 우리 모두 알고 있듯이 case x :: y은 유형의 모든 인스턴스 (기본 클래스는 ::)와 일치합니다. 따라서 나는 약간의 특별한 unapply가있을 것 같아 내 추측이 맞았다. 그것은 생성자 패턴이라고

+2

'::. unapply'가 존재합니다. 왜냐하면':'인 사례 클래스에 대해'unapply'가 자동으로 생성되기 때문입니다. –

+0

감사합니다. @ m-z,'x :: y'가'::'case 클래스의 인스턴스와 일치하는 이유를 이해할 수 있습니다. 하지만 왜 그것도 일반적인 클래스'::'의 기본 클래스 인 List와 일치하는지 알 수는 없습니다. –

+0

@mz, 내가 틀렸다면 나를 바로 잡아주세요, 자동으로 생성 된'D.unapply'는'D'의 인스턴스와 일치하지만 D의 기본 클래스는 일치하지 않습니다. –

답변

2

:

http://www.scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html#constructor-patterns

유형 (::) 단지 패턴 유형 (List)을 준수해야하고, 다음 "인수"패턴이 일치해야합니다.

추출기 패턴과 유사하지만 모양이 다릅니다.

scala> val vs = List(1,2,3) 
vs: List[Int] = List(1, 2, 3) 

scala> vs match { case 1 :: rest => "ok" } 
<console>:13: warning: match may not be exhaustive. 
It would fail on the following inputs: List((x: Int forSome x not in 1)), Nil 
     vs match { case 1 :: rest => "ok" } 
    ^
res0: String = ok 

scala> :javap -pv - 
[snip] 

    public $line4.$read$$iw$$iw$(); 
    descriptor:()V 
    flags: ACC_PUBLIC 
    Code: 
     stack=4, locals=5, args_size=1 
     0: aload_0 
     1: invokespecial #30     // Method java/lang/Object."<init>":()V 
     4: aload_0 
     5: putstatic  #32     // Field MODULE$:L$line4/$read$$iw$$iw$; 
     8: aload_0 
     9: getstatic  #35     // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$; 
     12: invokevirtual #39     // Method $line3/$read$$iw$$iw$.vs:()Lscala/collection/immutable/List; 
     15: astore_2 
     16: aload_2 
     17: instanceof #41     // class scala/collection/immutable/$colon$colon 
     20: ifeq   52 
     23: aload_2 
     24: checkcast  #41     // class scala/collection/immutable/$colon$colon 
     27: astore_3 
     28: aload_3 
     29: invokevirtual #45     // Method scala/collection/immutable/$colon$colon.head:()Ljava/lang/Object; 
     32: invokestatic #51     // Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I 
     35: istore  4 
     37: iconst_1 
     38: iload   4 
     40: if_icmpne  49 
     43: ldc   #53     // String ok 
     45: astore_1 
     46: goto   64 
     49: goto   55 
     52: goto   55 
     55: new   #55     // class scala/MatchError 
     58: dup 
     59: aload_2 
     60: invokespecial #58     // Method scala/MatchError."<init>":(Ljava/lang/Object;)V 
     63: athrow 
     64: aload_1 
     65: putfield  #28     // Field res0:Ljava/lang/String; 
     68: return 
[snip] 

아닌 빈 목록이 경우 X : Y 일치 :

편집 봐 엄마, 아니 추출기를 표시합니다. 내가 알고 싶은데, 왜 이 발생합니까?

비어 있지 않은 목록은 ::이어야합니다. 그것이 생성자 패턴에서 테스트합니다. 빈 목록 Nil은 그렇지 않습니다.

+0

감사합니다. @ som-snytt. 따라서 :: case 클래스의 존재는 ::에 대한 패턴 일치와는 아무런 관련이 없습니다. –

+0

사례 클래스이므로 ctor 패턴입니다. 관련 혼란 : https://issues.scala-lang.org/browse/SI-9795 –

+0

추출기 인 Contrast'scala> (1 :: Nil) match {case List (h) => h}'(unapplySeq). –