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]