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.1finalで実行すると、次の出力が得られます。

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ため、は一致 しません。そのため、そのメソッドは。に対して機能しません。::ListunapplyVector

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機能SeqLinearSeqます。IndexedSeqVector

  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 に答える