例如,
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
。更重要的是,使用Scala中的中缀符号,我们能够等效地写1 :: Nil
(尽管事实证明Nil.::(1)
将被调用而不是::(1, Nil)
,可能是由于一些优先规则。)
因此,我认为案例类::
与::
的模式匹配有关(例如,模式x :: y
将与::.unapply
匹配})。但我没有为案例类unapply
找到任何::
方法或伴随对象。
有谁能告诉我我的猜测是否正确?如果没有,那么在Scala中如何实现::
的模式匹配?
谢谢!
修改
显然,案例类为::
,::.unapply
将自动为::
生成case x :: y
。因此,我可以理解::
将匹配case x :: y
的实例(例如::( 1,2))。但是众所周知,List
也匹配::
类型的所有实例,它是unapply
的基类。因此,我认为可能有一些特殊的cat /tmp/*test1*
是我猜的正确。
答案 0 :(得分:2)
它被称为构造函数模式:
http://www.scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html#constructor-patterns
类型(::
)必须符合模式类型(List
),然后“arg”模式必须匹配。
它看起来类似于提取器模式,但不同。
编辑以显示外观,没有提取器:
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]
任何非空List都匹配大小写x :: y。我想知道为什么 这会发生吗?
非空列表必须是::
类型。这就是它在构造函数模式中测试的内容。空列表Nil
不是。