我在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)不编译。
答案 0 :(得分:0)
我可能会为您提供一个答案,而不是SeqFactory
:
Seq(1)
是Seq.apply(2)
的快捷方式,它方便地始终提供一个List
实例,即。这里List(2)
*。因此,它可以与(b)案件同化。Seq(1)
给出与List(1)
相匹配的case List(e)
)(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
}
。