我有很多模式匹配代码,如下所示:如果某些Foo
匹配,则返回Some
Bar
,否则为None
,并且有很多Foos
的{{1}}和Bars
的长构造函数。类似的东西:
y match {
case Foo1(z) => Some(Bar1(z))
case Foo2(z) => Some(Bar2(z))
case Foo3(z) => Some(Bar3(z))
case Foo4(z) => Some(Bar4(z))
case _ => None
}
在实际代码中,箭头右侧的构造函数更复杂,并且有更多的情况。
现在,为了摆脱重复的选项构造函数(Some
),我可以这样做:
Try(
y match {
case Foo1(z) => Bar1(z)
case Foo2(z) => Bar2(z)
case Foo3(z) => Bar3(z)
case Foo4(z) => Bar4(z)
}
).toOption
这对我来说看起来更清晰,从语义角度看它是合理的,因为case _
实际上是一种不应该发生的情况,因此将其建模为异常似乎是合理的。请注意,重复的Somes
会让我感到烦恼,而不是最后的case
。
我的问题是,我不知道后一种方法是否存在某些(例如性能)惩罚。
答案 0 :(得分:9)
第二个版本的可读性较差,而且不太正确*。如果您要将错误丢弃到Try
,则使用None
没有太大意义。 Try
只有 才能捕获匹配错误并将其转换为None
,但您可以使用case _ => None
进行匹配。
在Try
中会有更多的开销包装,但不够重要。首先要有正确性和可读性。
如果确实不希望出现这种情况,请考虑将y
包裹在Option
并使用collect
:
Option(y) collect {
case Foo1(z) => Bar1(z)
case Foo2(z) => Bar2(z)
case Foo3(z) => Bar3(z)
case Foo4(z) => Bar4(z)
}
在collect
上使用Option
会将案例包装在Some
中定义的部分函数中,任何不匹配的案例都将变为None
。< / p>
* 正确,我的意思是广泛接受使用Try
。