2012-08-28 22 views
1

我发现在使用orElse链接选项后,元素类型发生了更改,这使我无法按预期使用它。链接选项使用orElse更改元素类型

例如:一个类型为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之前,headNode型,这是正确的,但last也应该Node型的,但是编译器认为它是ScalaObject with Equals型的,我能不能通过last到功能采取Node作为参数。

我可以使用last.asInstanceOf[Node]来投射它,有没有办法避免这种投射,仍然会使last的类型为Node

回答

3

尝试此代替(注意添加括号):

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

的问题是,所述maporElse之后施加,而不是之前orElse。换句话说,表达式被解析这样的:

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

由于上的orElse左手侧的表达式的类型为Option[Option[Node]]但右手侧表达具有类型Option[Node]最低的共同父类型是Option[ScalaObject with Equals]

斯卡拉灵活的语法有时可以使编码非常好,但有时会导致这样的疯狂的事情。对于像这样的复杂表达式,添加括号以使您的意思更加明确是个不错的主意。

+0

你说得对。 'orElse'只能看到xml.lastOption。 – Sawyer

0

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

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

xml.LastOption具有类型Option[Node]

所以当你做orElse bettwen他们会寻找最精确的公用超类型(最小上界)的None.typeNode。并没有任何兴趣,它恰好是ScalaObject with Equals,它可能就是AnyRef

您的最终map {last => Some(last)}也很奇怪。你打算在那里做什么?

1

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

xml.headOption.orElse(xml.lastOption) 

虽然值得注意的是,如果headOption是无,所以将lastOption是。

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