Scala ::的模式匹配是如何实现的?

Scala ::的模式匹配是如何实现的?,scala,pattern-matching,Scala,Pattern Matching,比如说, List(1, 2, 3) match { case x :: y => (x, y) } 在上面的代码中,模式匹配将自动发现任何非空的列表都匹配大小写x::y。我想知道,为什么会这样 我们都知道,类中有一个:方法。此外,我发现“list.scala”中有一个:case类: 因此,我们可以编写:(1,Nil)来构建一个新的列表。更重要的是,使用Scala中的中缀符号,我们可以等价地编写1::Nil(尽管结果是Nil::(1)将被调用,而不是::(1,Nil),可能是由于一些

比如说,

List(1, 2, 3) match {
  case x :: y => (x, y)
}
在上面的代码中,模式匹配将自动发现任何非空的
列表
都匹配大小写
x::y
。我想知道,为什么会这样

我们都知道,
类中有一个
方法。此外,我发现“list.scala”中有一个
case类:

因此,我们可以编写
:(1,Nil)
来构建一个新的
列表。更重要的是,使用Scala中的中缀符号,我们可以等价地编写
1::Nil
(尽管结果是
Nil::(1)
将被调用,而不是
::(1,Nil)
,可能是由于一些优先规则。)

因此,我猜case类
::
的模式匹配有关(例如,模式
x::y
将由类似
::.unapply
的内容进行匹配)。但是我没有找到任何不适用于case类的
方法或伴随对象

谁能告诉我我的猜测是否正确?如果没有,那么在Scala中如何实现
的模式匹配

谢谢

编辑:


显然,case类as
是一个
::。将自动为
生成unapply
。因此,我可以理解
案例x::y
将匹配
::
的实例(例如,::(1,2))。但是我们都知道,
案例x::y
也匹配类型
List
的所有实例,这是
的基类。因此,如果我的猜测是正确的,我想可能会有一些特殊的
不适用的

它被称为构造函数模式:

类型(
)只需符合模式类型(
列表
),然后“arg”模式必须匹配

它看起来类似于提取器模式,但不同

编辑以显示look ma,无提取器:

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]
scala>val vs=List(1,2,3)
vs:List[Int]=List(1,2,3)
scala>vs匹配{case 1::rest=>ok}
:13:警告:匹配可能不完整。
它将在以下输入上失败:List((x:Int表示某些x不在1中)),Nil
vs匹配{case 1::rest=>“ok”}
^
res0:String=ok
scala>:javap-pv-
[剪报]
公共$line4.$read$$iw$$iw$();
描述符:()V
旗帜:ACC_PUBLIC
代码:
堆栈=4,局部变量=5,参数大小=1
0:aload_0
1:invokespecial#30//方法java/lang/Object。“:()V
4:aload_0
5:putstatic#32//字段模块$:L$line4/$read$$iw$$iw$;
8:aload_0
9:getstatic#35//字段$line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
12:invokevirtual#39//方法$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//类scala/collection/immutable/$colon$colon
27:astore_3
28:aload_3
29:invokevirtual#45//方法scala/collection/immutable/$colon$colon.head:()Ljava/lang/Object;
32:invokestatic#51//方法scala/runtime/BoxesRunTime.unextpoint:(Ljava/lang/Object;)I
35:istore 4
37:iconst_1
38:iload 4
40:if_icmpne 49
43:ldc#53//字符串正常
45:astore_1
46:转到64
49:goto 55
52:转到55
55:new#55//class scala/MatchError
58:dup
59:aload_2
60:invokespecial#58//方法scala/MatchError。“:(Ljava/lang/Object;)V
63:athrow
64:aload_1
65:putfield#28//Field res0:Ljava/lang/String;
68:返回
[剪报]
任何非空列表都与案例x::y匹配。我想知道,为什么 这会发生吗


非空列表的类型必须为
。这就是它在构造函数模式中测试的内容。空列表
Nil
,不存在。

::.unapply
之所以存在,是因为
unapply
是为案例类自动生成的,而
::
是。谢谢@m-z,我可以理解为什么
x::y
会匹配
案例类的实例。但是我不明白为什么它也匹配一个通用的
列表
,它是case class
的基类::
@m-z,如果我错了,请纠正我,我认为自动生成的
D.unapply
只匹配
D的实例,而不匹配D的基类。@m-z unapply不用于构造函数模式,不是你们说的那个样。Scala中的模式匹配是通过使用伴随对象的unapply方法作为提取器来工作的。您可以在Thank@som snytt的第1部分和第2部分中了解更多关于它们的信息。所以::case类的存在与::的模式匹配无关,对吗?它是一个ctor模式,因为它是一个case类。相关的混淆:对比度
scala>(1::Nil)匹配{case List(h)=>h}
,这是一个提取器(一个unallyseq)。这很奇怪。为什么
列表(1,2,3)。isInstanceOf[:[Int]
给出
true
?我认为
(case类)是
列表的一个子类型。(对不起,我是Scala的新手)对不起,也许我没有表达清楚。多亏了你们的帮助,我已经理解了提取器和构造函数模式之间的区别。但是我仍然有一个问题,为什么
列表(1,2,3).isInstanceOf[::[Int]]
给出
true
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]