1

我发现使用 orElse 链接 Option 后,元素类型发生了变化,这使我无法按预期使用它。

例如:类型为 .xml 的 xml NodeSeq

scala> xml1.headOption map { head => None } orElse xml2.lastOption map {last => Some(last)}
res11: Option[Some[ScalaObject with Equals]] = Some(Some(None))

orElse,之前head是 type Node,这是正确的,但last也应该是 type Node,但编译器认为它是 type ScalaObject with Equals,我不能传递last给以 aNode作为参数的函数。

我可以使用它进行投射last.asInstanceOf[Node],有没有办法避免这种投射并且仍然使用last类型Node

4

3 回答 3

3

试试这个(注意添加的括号):

(xml.headOption map { head => None }) orElse (xml.lastOption map {last => Some(last)})

问题是map被应用 afterorElse而不是 before orElse。换句话说,表达式是这样解析的:

((xml.headOption map { head => None }) orElse xml.lastOption) map {last => Some(last)}

由于左侧的表达式orElse具有类型Option[Option[Node]]但右侧的表达式具有类型Option[Node],因此最低的公共超类型是Option[ScalaObject with Equals]

Scala 的灵活语法有时可以使编码变得非常好,但有时它会导致像这样疯狂的事情。对于像这样的复杂表达式,最好添加括号以使您的意思更明确。

于 2012-08-28T10:11:36.180 回答
1

一般来说,我认为你需要重新检查你到底在做什么,因为它没有多大意义。xml.headOption map { head => None }总是会解决Some(None)(在你的情况下),这很少是你想要的。我最好的猜测是你想要这样的东西:

xml.headOption.orElse(xml.lastOption)

虽然值得注意的是,如果 headOption 为 None,那么 lastOption 也是。

编辑:正如道文所指出的,在这个例子中很可能推断出正确的上限Option[Node],而掩盖它的问题是错误orElse被调用的问题。但是,我仍然认为这里的真正问题是您所做的事情没有多大意义,可能应该重新考虑。

于 2012-08-28T10:04:00.443 回答
0

map {head => None}可能不是你想要的。这是一个错字吗?

之后,你有一个Option[None.type],一个不太有趣的类型,它只有两个可能的值,NoneSome(None)。由于您的 xml 不是空的,它恰好是 Some(None)。

xml.LastOption有类型Option[Node]

因此,当您对orElse它们进行比较时,它会寻找最精确的常见超类型(最小上限)None.typeNode。而且没有兴趣,它恰好是ScalaObject with Equals,它也可能是AnyRef

你的决赛map {last => Some(last)}也很奇怪。你在那里有什么打算?

于 2012-08-28T10:03:17.973 回答