我在scala中使用了很多模式匹配。很多时候我需要做一些计算,在警卫部分,有时他们是相当昂贵的。有没有办法将计算值绑定到单独的值?
//i wan't to use result of prettyExpensiveFunc in body safely
people.collect {
case ...
case Some(Right((x, y))) if prettyExpensiveFunc(x, y) > 0 => prettyExpensiveFunc(x)
}
//ideally something like that could be helpful, but it doesn't compile:
people.collect {
case ...
case Some(Right((x, y))) if {val z = prettyExpensiveFunc(x, y); y > 0} => z
}
//this solution works but it isn't safe for some `Seq` types and is risky when more cases are used.
var cache:Int = 0
people.collect {
case ...
case Some(Right((x, y))) if {cache = prettyExpensiveFunc(x, y); cache > 0} => cache
}
有没有更好的解决办法?ps:示例是简化的,我不期望答案表明我不需要模式匹配在这里。
3条答案
按热度按时间czq61nw11#
您可以使用
cats.Eval
使昂贵的计算变得懒惰和可记忆,使用.map
创建Eval
,并在.collect
中提取.value
(如果需要,最多计算一次如果不创建一些惰性评估的实现,我看不到一种方法来做你想做的事情,如果你必须使用一个,你最好使用现有的一个,而不是自己滚动一个。
如果你还没有注意到的话,编辑一下,你并没有因为在这里使用元组而失去模式匹配的能力:
amrnrhlw2#
为什么不先对每个元素运行这个函数,然后再处理元组呢?
qoefvg9y3#
我尝试了自己的匹配器和效果是某种程度上可以,但不完美。我的matcher是untyped的,要使它完全类型化有点难看。
https://scalafiddle.io/sf/hFbcAqH/3