3

有没有理由match写反对在类型上的Seq工作方式与在类型上的工作方式不同?对我来说,无论输入类型如何,下面的代码似乎都应该做同样的事情。当然不会,否则我不会问。IndexedSeqLinearSeq

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 上运行它,我得到以下输出:

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 的东西却失败了。我错过了什么吗?这是编译器错误吗?

scalac -print输出m看起来像:

@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)
  }
};
4

3 回答 3

16

您不能::用于除List. Vector无法匹配,因为 它::是一个扩展的案例类List,因此它的unapply方法不适用于Vector

val a :: b = List(1,2,3)    // fine
val a :: b = Vector(1,2,3)  // error

但是您可以定义自己的适用于所有序列的提取器:

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
于 2012-04-17T21:27:58.393 回答
0

跟随模式匹配适用于List, Seq, LinearSeq, IndexedSeq, Vector.

  Vector(1,2) match {
  case a +: as => s"$a + $as"
  case _      => "empty"  
}
于 2018-11-23T10:39:31.133 回答
0

在 Scala 2.10中是在本次提交object +:中引入的。从那时起,对于每个,您可以执行以下操作:SeqLike

@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)
    }
  }
}

代码在Scastie运行。

于 2021-03-25T14:30:50.473 回答