以下命令式代码最有效的函数版本是什么?
我正在学习 Scala,我想知道使用 Scala 的函数式编程功能表达这种命令式模式的最佳方式。
def f(l: List[Int]): Boolean = {
for (e <- l) {
if (test(e))
return true
}
}
return false
}
我能想到的最好的办法是:
l map { e => test(e) } contains true
但这效率较低,因为它在每个元素上调用 test() ,而命令式版本则在满足 test() 的第一个元素上停止。是否有更惯用的函数式编程技术可以达到相同的效果?命令式版本在 Scala 中似乎很尴尬。
I'm learning Scala and I want to know the best way of expressing this imperative pattern using Scala's functional programming capabilities.
def f(l: List[Int]): Boolean = {
for (e <- l) {
if (test(e))
return true
}
}
return false
}
The best I can come up with is along the lines of:
l map { e => test(e) } contains true
But this is less efficient since it calls test() on each element, whereas the imperative version stops on the first element that satisfies test(). Is there a more idiomatic functional programming technique I can use to the same effect? The imperative version seems awkward in Scala.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用exists方法:
如果您不熟悉这样使用的_,它相当于:
You can use the exists method:
If you are not familiar with the _ used like this, it's the equivalent of:
因此,您需要的是
exists
方法 (l.exists(test)
),它没有说明您如何实现它。最简单的实现并不是很高效:问题是它将迭代所有
l
,即使一旦flag
变为 true 测试就会停止。现在,大多数函数式迭代方法(在严格的语言中)在完成所有集合之前不会停止迭代。那些实际上的实现方式与您的实现方式非常相似,因此,最终您只是隐藏了此类代码,而不是避免它。然而,如果我被要求使用现有的方法,当然,不使用
exists
,并且在此之上保持高效,人们可以这样做:So, what you want is the
exists
method (l.exists(test)
), which says nothing of how you'd implement it. The simplest implementation isn't very efficient:The problem is that it will iterate through all of
l
, even if the testing stops onceflag
becomes true. Now, most functional methods of iteration (in strict languages) will not stop iterating until finished through all the collection. The ones that do are actually implemented pretty much like you did, so, in the end, you are just hiding that sort of code, not avoiding it.However, if I were required to use existing methods, and, of course, not to use
exists
, and be efficient on top of that, one could do something like this:当然,在这种情况下没有必要(我实际上希望 Scala 库为自己的
exists
使用更命令式的版本 - 或者至少有一个map
显式的break
),但在List
上,您可以使用简单的(尾)递归函数。因为如果左侧为 false,则
||
仅评估右侧,这意味着您会提前中断。当然,只有当引用集合的尾部成本很低时,这才是有效的。
Of course it isn’t necessary in this case (and I actually expect the Scala library to use a more imperative version for their own
exists
– or at least have amap
with an explicitbreak
in it) but on aList
you can use a simple (tail) recursive function.Because
||
only evaluates the right side if the left side isfalse
it means you break early.This, of course, is only efficient if referencing the tail of a collection is cheap.