匹配接收到IndexedSeq而不是LinearSeq时的MatchError [英] MatchError when match receives an IndexedSeq but not a LinearSeq
问题描述
是否有理由针对Seq
编写的match
在IndexedSeq
类型上的工作方式与在LinearSeq
类型上的工作方式不同?在我看来,无论输入类型如何,以下代码都应该执行完全相同的操作.当然不是,或者我不会问.
Is there a reason that match
written against Seq
would work differently on IndexedSeq
types than the way it does on LinearSeq
types? To me it seems like the code below should do the exact same thing regardless of the input types. Of course it doesn't or I wouldn't be asking.
import collection.immutable.LinearSeq
object vectorMatch {
def main(args: Array[String]) {
doIt(Seq(1,2,3,4,7), Seq(1,4,6,9))
doIt(List(1,2,3,4,7), List(1,4,6,9))
doIt(LinearSeq(1,2,3,4,7), LinearSeq(1,4,6,9))
doIt(IndexedSeq(1,2,3,4,7), IndexedSeq(1,4,6,9))
doIt(Vector(1,2,3,4,7), Vector(1,4,6,9))
}
def doIt(a: Seq[Long], b: Seq[Long]) {
try {
println("OK! " + m(a, b))
}
catch {
case ex: Exception => println("m(%s, %s) failed with %s".format(a, b, ex))
}
}
@annotation.tailrec
def m(a: Seq[Long], b: Seq[Long]): Seq[Long] = {
a match {
case Nil => b
case firstA :: moreA => b match {
case Nil => a
case firstB :: moreB if (firstB < firstA) => m(moreA, b)
case firstB :: moreB if (firstB > firstA) => m(a, moreB)
case firstB :: moreB if (firstB == firstA) => m(moreA, moreB)
case _ => throw new Exception("Got here: a: " + a + " b: " + b)
}
}
}
}
在2.9.1 final上运行此命令,我得到以下输出:
Running this on 2.9.1 final, I get the following output:
OK! List(2, 3, 4, 7)
OK! List(2, 3, 4, 7)
OK! List(2, 3, 4, 7)
m(Vector(1, 2, 3, 4, 7), Vector(1, 4, 6, 9)) failed with scala.MatchError: Vector(1, 2, 3, 4, 7) (of class scala.collection.immutable.Vector)
m(Vector(1, 2, 3, 4, 7), Vector(1, 4, 6, 9)) failed with scala.MatchError: Vector(1, 2, 3, 4, 7) (of class scala.collection.immutable.Vector)
对于List-y,它运行良好,但对于Vector-y,则运行失败.我想念什么吗?这是编译器错误吗?
It runs fine for List-y things, but fails for Vector-y things. Am I missing something? Is this a compiler bug?
m
的scalac -print
输出如下:
@scala.annotation.tailrec def m(a: Seq, b: Seq): Seq = {
<synthetic> val _$this: object vectorMatch = vectorMatch.this;
_m(_$this,a,b){
<synthetic> val temp6: Seq = a;
if (immutable.this.Nil.==(temp6))
{
b
}
else
if (temp6.$isInstanceOf[scala.collection.immutable.::]())
{
<synthetic> val temp8: scala.collection.immutable.:: = temp6.$asInstanceOf[scala.collection.immutable.::]();
<synthetic> val temp9: Long = scala.Long.unbox(temp8.hd$1());
<synthetic> val temp10: List = temp8.tl$1();
val firstA$1: Long = temp9;
val moreA: List = temp10;
{
<synthetic> val temp1: Seq = b;
if (immutable.this.Nil.==(temp1))
{
a
}
else
if (temp1.$isInstanceOf[scala.collection.immutable.::]())
{
<synthetic> val temp3: scala.collection.immutable.:: = temp1.$asInstanceOf[scala.collection.immutable.::]();
<synthetic> val temp4: Long = scala.Long.unbox(temp3.hd$1());
<synthetic> val temp5: List = temp3.tl$1();
val firstB: Long = temp4;
if (vectorMatch.this.gd1$1(firstB, firstA$1))
body%11(firstB){
_m(vectorMatch.this, moreA, b)
}
else
{
val firstB: Long = temp4;
val moreB: List = temp5;
if (vectorMatch.this.gd2$1(firstB, moreB, firstA$1))
body%21(firstB,moreB){
_m(vectorMatch.this, a, moreB)
}
else
{
val firstB: Long = temp4;
val moreB: List = temp5;
if (vectorMatch.this.gd3$1(firstB, moreB, firstA$1))
body%31(firstB,moreB){
_m(vectorMatch.this, moreA, moreB)
}
else
{
body%41(){
throw new java.lang.Exception("Got here: a: ".+(a).+(" b: ").+(b))
}
}
}
}
}
else
{
body%41()
}
}
}
else
throw new MatchError(temp6)
}
};
推荐答案
除List
之外,不能将::
用作其他任何内容. Vector
无法匹配,因为::
是扩展List
的案例类,因此其unapply
方法不适用于Vector
.
You can't use ::
for anything other than List
. The Vector
is failing to match because ::
is a case class that extends List
, so its unapply
method does not work for Vector
.
val a :: b = List(1,2,3) // fine
val a :: b = Vector(1,2,3) // error
但是您可以定义自己的提取器,该提取器适用于所有序列:
But you can define your own extractor that works for all sequences:
object +: {
def unapply[T](s: Seq[T]) =
s.headOption.map(head => (head, s.tail))
}
因此您可以这样做:
val a +: b = List(1,2,3) // fine
val a +: b = Vector(1,2,3) // fine
这篇关于匹配接收到IndexedSeq而不是LinearSeq时的MatchError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!