我发现在使用orElse链接Option之后,元素类型发生了变化,这使我无法按预期使用它。
例如:一个类型为NodeSeq
的xml。
scala> xml1.headOption map { head => None } orElse xml2.lastOption map {last => Some(last)}
res11: Option[Some[ScalaObject with Equals]] = Some(Some(None))
在orElse
之前,head
的类型为Node
,这是正确的,但last
也应该是Node
类型,但编译器认为它的类型为ScalaObject with Equals
,我无法将last
传递给函数,并将Node
作为参数。
我可以使用last.asInstanceOf[Node]
来投射它,有没有办法避免这种投射,仍然可以last
类型Node
?
答案 0 :(得分:3)
请尝试这样做(注意添加的括号):
(xml.headOption map { head => None }) orElse (xml.lastOption map {last => Some(last)})
问题是在map
之后而不是在orElse
之前应用orElse
。换句话说,表达式解析如下:
((xml.headOption map { head => None }) orElse xml.lastOption) map {last => Some(last)}
由于orElse
左侧的表达式具有类型Option[Option[Node]]
,但右侧表达式的类型为Option[Node]
,因此最低常见超类型为Option[ScalaObject with Equals]
}。
Scala灵活的语法有时会使编码变得非常好,但有时会导致像这样的疯狂事情。对于像这样的复杂表达式,最好添加括号以使您的意思更明确。
答案 1 :(得分:1)
总的来说,我认为你需要重新审视自己到底在做什么,因为它没有多大意义。 xml.headOption map { head => None }
始终会解析为Some(None)
(在您的情况下),这很少是您想要的。我最好的猜测是你想要的东西:
xml.headOption.orElse(xml.lastOption)
虽然值得注意的是,如果headOption为None,那么lastOption也是如此。
编辑:正如道文指出的那样,在这个例子中很有可能推断出Option[Node]
的正确上限,并且模糊它的问题是被调用的错误orElse
。但是,我仍然认为这里真正的问题是你所做的事情没有多大意义,应该重新考虑。
答案 2 :(得分:0)
map {head => None}
可能不是你想要的。这是一个错字?
之后,您有一个Option[None.type]
,一个不太有趣的类型,它只有两个可能的值,None
和Some(None)
。
由于您的xml不为空,它恰好是Some(None)。
xml.LastOption
的类型为Option[Node]
因此,当你在orElse
之间进行操作时,它会查找None.type
和Node
的最精确的常见超类型(最小上限)。并且没有任何兴趣,它恰好是ScalaObject with Equals
,它也可能是AnyRef
。
你的最终map {last => Some(last)}
也很奇怪。你打算做什么?