在Scala中,for
和for-yield
循环通常会转换为使用Lambdas进行map
,flatMap
和filter
调用的序列。由于编译器将Lambdas转换为匿名类而不是Java 8的花哨invokedynamic
/ LambdaMetafactory
/ Unsafe.defineAnonymousClass
系统。这显然会为临时类及其实例带来大量开销,以及map,flatMap和filter操作的开销,这些操作通常会复制其底层集合。当通常更快的迭代方法可用时,至少在字节码级别上,有没有特别的理由使用函数方法解决问题?
例如,为什么
for {
sl <- l
el <- sl
if el > 0
} println el.toString.length
翻译为
l.flatMap(sl => sl.filter(el => el > 0).foreach(el => println el.toString.length))
而不是
for (sl <- l) // Iterable for loop
{
for (el <- sl) // Iterable for loop
{
println el.toString.length
}
}
答案 0 :(得分:1)
这是以这种方式实现的,因为SLS是如何定义它的。粘贴在这里的规则相当大,但它们完全包含在规范中。
For Comprehensions and For Loops
示例强> 以下代码生成1和1之间的所有数字对 n-1,其总和为素数。
for { i <- 1 until n j <- 1 until i if isPrime(i+j) } yield (i, j)
for comprehension转换为:
(1 until n) .flatMap { case i => (1 until i) .withFilter { j => isPrime(i+j) } .map { case j => (i, j) } }