因为所有你检查的存在,你可以组成2种的用途exists
:
(0 until x).exists(i => (i + 1 until x).exists(fn(i, _)))
更一般地,如果您关心的不仅仅是确定一个特定的元素存在更多,您可以将您的理解转化为一系列Streams
,Iterators
,或views
,您可以用exists
,它会延迟计算,避免了环路的不必要的执行:
def foo(x: Int, fn: (Int, Int) => Boolean): Boolean = {
(for {
i <- (0 until x).iterator
j <- (i + 1 until x).iterator
} yield(i, j)).exists(fn.tupled)
}
您还可以使用map
和flatMap
代替for
和toStream
或view
,而不是iterator
:
(0 until x).view.flatMap(i => (i + 1 until x).toStream.map(j => i -> j)).exists(fn.tupled)
您还可以在任何收藏上使用view
来获得所有变形金刚懒惰执行的集合。这可能是短路收集遍历的最常用的方式。从the docs on views
:
Scala集合默认情况下,严格在其所有的变压器,除了Stream
,它懒洋洋地实现其所有变压器的方法。但是,有一种系统的方法可以将每个收藏集变成懒惰的收藏集,反之亦然,这是基于收集的意见。视图是一种特殊的集合,它代表了一些基本集合,但是却懒散地实现了所有变形。
就开销而言,它确实取决于具体细节!不同的集合具有可能在开销量上有所不同的view
,toStream
和iterator
的不同实现。如果fn
计算起来非常昂贵,那么这个开销可能是值得的,并且为您的代码保留一致的,惯用的功能样式使其更具可维护性,可调试性和可读性。如果您处于需要极端优化的情况下,您可能需要回退到return
等较低级别的构造(这不是没有它自己的开销!)。
你可以看看尾递归 – cchantep