Scala中的模式匹配分配

时间:2015-12-23 00:39:40

标签: scala pattern-matching

我在scala中通过模式匹配进行分配时遇到问题。假设我有以下内容:

a. Seq.unapplySeq(List(1))

b. val Seq(z) = List(1)

c. val c = List(1) match {
  case Seq(e) => e
}

d. List.unapplySeq(Seq(1))

e. val List(a) = Seq(1)

f. val b = Seq(1) match {
  case List(e) => e
}

只有(d)不编译,其他编译和运行正确。

我知道列表的unapplySeq在SeqFactory中定义为:

abstract class SeqFactory[CC[X] <: Seq[X] with GenericTraversableTemplate[X, CC]] extends GenSeqFactory[CC] with TraversableFactory[CC] {
    applySeq[A](x: CC[A]): Some[CC[A]] = Some(x)
}

因为CC是List,所以(d)中的Seq不会进行类型检查。

似乎(a),(b)和(c)属于一组,(d),(e)和(f)属于另一组。

根据我的理解,(f)的破坏实际上会调用(d),因为(f)中的模式匹配是使用List来破坏Seq(1)。

我的问题是为什么(e)和(f)仍然是正确的(d)不编译。

2 个答案:

答案 0 :(得分:0)

我可能会为您提供一个答案,而不是SeqFactory

  1. (e)编译并运行,因为Seq(1)Seq.apply(2)的快捷方式,它方便地始终提供一个List实例,即。这里List(2) *。因此,它可以与(b)案件同化。
  2. (f)出于相同的前述原因进行编译和运行(Seq(1)给出与List(1)相匹配的case List(e)
  3. (d)无法编译,因为我在第一点关于(e)案例的内容是关于实例而不是类型的。 Seq(1)List的实例,但类型为Seq。这是一个演示:

    List.unapplySeq(Seq(1))
    

    等同于

    List.unapplySeq(List(1).asInstanceOf[Seq[Int]])
    

    并给出:

    *error: type mismatch;*
    

    而:

    List.unapplySeq(List(1))
    

    等效于:

    List.unapplySeq(Seq(1).asInstanceOf[List[Int]])
    

    都给出:

    Some(List(1))
    

但是,这是困难所在,您需要了解(f)模式匹配的好奇心:它的行为就像scala在内部将其键入为List而不是Seq

这是我的解释模式匹配,并不关心输入的类型。就这么简单(例如,参见https://www.scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html#variable-patterns)。这是一个演示:

    var foo: Seq[Int] = List(1)
    foo match { case _: List[Int] => true } // gives true
    foo = 1 to 3
    foo match { case _: List[Int] => true } // throws scala.MatchError

希望有帮助。

*更清楚地说,如果在另一个scala实现中,此应用将给定Vector(2),则错误不是在编译期间而是在运行时弹出(Alexey Romanov对此做了很好的论述)

答案 1 :(得分:0)

(e)被翻译为(f),正确。但是,如果您查看https://www.scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html#pattern-sequences,则对Select * from yourtable union select 'Total', ' ', ' ', ' ', sum(buy_price) from yourtable 的唯一要求是结果类型,而不是参数类型。因此,我的猜测(该规范实际上并未对此进行指定,并且我目前无法检查)是:(f)在调用unapplySeq之前测试其参数为List,即内部存在某种东西喜欢

unapplySeq

请注意,该参数也适用于Seq(1) match { case canUnapplySeq: List[Int] => ... List.unapplySeq(canUnapplySeq) // (d) only invoked here }