用于vararg的Scala模式匹配

piy*_*thi 3 scala pattern-matching

我只是想在scala上做一些动手并尝试自己实现List.concat函数.这是代码

  def concat[A](lists : Traversable[A]*):List[A]={
    println("concat called")
    lists match {
      case Nil => Nil
      case x :: Nil => (x :\ List.empty[A])((elem,list)=> elem::list)
      case x:: xs => (x :\ concat(xs:_*))((elem,list)=> elem :: list)
    }
  }
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试调用此方法时

concat(List(1,2,3),List(2,3,4),List(4,5,6),List(6,7,8))
Run Code Online (Sandbox Code Playgroud)

我收到错误

Exception in thread "main" scala.MatchError: WrappedArray(List(1, 2, 3), List(2, 3, 4), List(4, 5, 6), List(6, 7, 8)) (of class scala.collection.mutable.WrappedArray$ofRef)
Run Code Online (Sandbox Code Playgroud)

谁能解释我在这里做错了什么?提前致谢

Łuk*_*asz 7

Varags是一个Seq,你可以匹配它Seq,就像在列表上一样.这是一个例子:

@ a(1, 2, 3) 
res1: Seq[Int] = Array(1, 2, 3)
@ def a(x: Int*) = x match {
                  case Seq() => "empty"
                  case Seq(a) => s"single $a"
                  case Seq(a, as @ _*) => s"multiple: $a, $as"
                } 
defined function a
@ a(1, 2, 3, 4) 
res3: String = "multiple: 1, WrappedArray(2, 3, 4)"
@ a(1, 2) 
res4: String = "multiple: 1, WrappedArray(2)"
@ a(1) 
res5: String = "single 1"
Run Code Online (Sandbox Code Playgroud)

进行这样的匹配Nil并且x :: xs通常意味着您可以简单地使用foldLeft,这就是这样.

def concat[A](lists: Traversable[A]*): List[A] =
    lists.foldLeft(List.empty[A])(_ ++ _)
Run Code Online (Sandbox Code Playgroud)

请注意,匹配Nilx :: xs,在哪里xs可以Nil,就足够了.你的第二个case可以简单地删除.

看看那些:

case Nil => Nil
case x :: Nil => (x :\ List.empty[A])(_ :: _)
case x :: xs  => (x :\ concat(xs:_*))(_ :: _)
Run Code Online (Sandbox Code Playgroud)

最后两个是一样的.如果在第三种情况下,xs == Nil那么代替concat(xs:_*)你将得到你的Nil,这与List.empty[A](如果类型被正确推断)相同.