
[英]Why can I not use :: after a list to append a string to it in Scala?
[英]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:通常应使用模式匹配或高阶函数来处理列表,而不要使用head
和tail
。
问题是附加操作:+接受一个非列表值并将其附加到列表中。 麻烦的是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.