链接映射是否由编译器优化?

Apo*_*orv 5 scala compiler-optimization

Scala 有一种使用mapconstruct将集合转换为另一个集合的惊人方法。

val l = List(1, 2, 3, 4)
l.map(_*_)
Run Code Online (Sandbox Code Playgroud)

将返回列表中元素的平方 l

我遇到了多个地图链接在一起的各种情况,比如,

val l = List(1, 2, 3, 4)
val res = l.map(_ * _).map(_ + 1).filter(_ < 3)
Run Code Online (Sandbox Code Playgroud)

我相信下面发生的事情等同于下面的事情。

val l = List(1, 2, 3, 4)
val l1 = l.map(_*_)
val l2 = l1.map(_ + 1)
val res = l2.filter(_ < 3)
Run Code Online (Sandbox Code Playgroud)

创建l1l2如果集合过大可能会导致内存问题。为了解决这个问题,Scala 编译器有什么优化吗?

val l = List(1, 2, 3, 4)
val res = l1.map( _*_ + 1).filter(_ < 3)
Run Code Online (Sandbox Code Playgroud)

一般来说,如果f, g,h是函数

val l = List(/*something*/)
val res = l.map(f(_)).map(g(_)).map(h(_))
Run Code Online (Sandbox Code Playgroud)

可以转换成

val res = l.map(f _ andThen g _ andThen h _)
Run Code Online (Sandbox Code Playgroud)

Ale*_*nov 1

不,因为这需要编译器了解map专门实现它的标准库类的语义并对其进行处理(因为没有人阻止您编写不成立的类)。有一项研究提案可能最终会实现这一点……最终。

还有Scala-Blitz优化了一些收集操作,但是融合和森林砍伐在本次演示中被列为未来的工作,我认为它们还没有实现。

正如 Steve Waldman 的回答所说,使用Stream(或者更好的是,Iterator)可以有所帮助,但它不会完全消除中间集合。