我只是想在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)
}
}
然而,当我尝试将此方法称为
时concat(List(1,2,3),List(2,3,4),List(4,5,6),List(6,7,8))
我收到错误
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)
有人可以解释我在这里做错了吗? 提前致谢
答案 0 :(得分:6)
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"
在Nil
和x :: xs
上进行此类匹配通常意味着您只需使用foldLeft
即可。
def concat[A](lists: Traversable[A]*): List[A] =
lists.foldLeft(List.empty[A])(_ ++ _)
请注意,匹配Nil
和x :: xs
,其中xs
可以是Nil
就足够了。您的第二个case
可以被删除。
看看那些:
case Nil => Nil
case x :: Nil => (x :\ List.empty[A])(_ :: _)
case x :: xs => (x :\ concat(xs:_*))(_ :: _)
最后两个是一样的。如果在第三种情况下xs == Nil
代替concat(xs:_*)
,您将获得Nil
,与List.empty[A]
相同(如果类型被正确推断)。
答案 1 :(得分:3)
Nil
是List
:
scala> Nil
res11: scala.collection.immutable.Nil.type = List()
但是,Scala将所有可变参数包装到Seq
(WrappedArray
实现Seq
)中,这就是您获得MatchError
的原因。您可以通过以下方式重写您的功能:
scala> def concat[A](lists : Traversable[A]*):List[A]={
| lists match {
| case Seq() => Nil
| case x +: Seq() => (x :\ List.empty[A])((elem,list)=> elem::list)
| case x +: xs => (x :\ concat(xs:_*))((elem,list)=> elem :: list)
| }
| }
concat: [A](lists: Traversable[A]*)List[A]
scala> concat(List(1), List(2), List(3))
res9: List[Int] = List(1, 2, 3)
您还可以使用flatMap
简化您的功能:
scala> def concat[A](lists: Traversable[A]*): List[A] = {
| lists.flatMap(x => x).toList
| }
concat: [A](lists: Traversable[A]*)List[A]
scala> concat(List(1), List(2), List(3))
res16: List[Int] = List(1, 2, 3)