繁体   English   中英

为什么不能将Nil追加到列表中?

[英]Why can't I append Nil to a list?

我有以下递归方法:

def myMethod(foo: List[FooBar], acc: List[MyClass]): List[MyClass] {

   // ... some code ...

   myMethod(foo.tail, acc :+ getMyObject(foo.head).getOrElse(Nil))

}

方法getMyObject可选地返回MyClass的实例。 不幸的是,我无法编译此代码,因为出现此错误:

[error]  found   : List[Product with Serializable]
[error]  required: List[MyClass]

此编译错误表明我无法将Nil追加到列表acc ,因此我必须使用以下代码:

def myMethod(foo: List[FooBar], acc: List[MyClass]): List[MyClass] {

   // ... some code ...
   val bar = getMyObject(foo.head)
   myMethod(foo.tail, if (bar.isDefined) acc :+ bar.get else acc)

}

但是,我更喜欢第一种方法,因为它更简洁。 为什么不能将Nil追加到列表中?

:+接受一个n元素列表和一个元素x并返回一个n+1元素列表,其中最后一个元素为x 这意味着两件事:

  • 没有参数可以用作:+的正确操作数来获取相同大小的列表
  • :+的右操作数必须是列表的元素类型。

因此,只有在acc是列表列表的情况下,才可以执行acc :+ Nil ,即使这样它也不会做您想要的事情,因为它将在列表中添加一个额外的空列表,而不是使列表保持不变。


解决问题的最简洁方法是acc ++ bar 这使用串联而不是附加操作,因为选项被视为0或1个元素的集合。 所以acc ++ bar追加的零个或一个元件bar的那些的acc

PS:通常应使用模式匹配或高阶函数来处理列表,而不要使用headtail

问题是附加操作:+接受一个非列表值并将其附加到列表中。 麻烦的是Nil和Myclass是不同的类型,因此结果列表采用了同时满足MyClass和Nil的最特定类型。 它们是完全无关的类型,因此您最终会获得Product with Serializable作为常见的超级类型。

要将元素或什么都不添加到列表,请首先将该元素包装到列表中。 然后将您的单例列表或Nil与旧列表连接在一起。

myMethod(foo.tail, acc ++ getMyObject(foo.head).map(x => List(x)).getOrElse(Nil))

您使用了错误的运算符,请改用++

myMethod(foo.tail, acc ++ getMyObject(foo.head).map(List(_)).getOrElse(Nil))

要么

myMethod(foo.tail,  getMyObject(foo.head).map(acc :+ _).getOrElse(acc))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM