Scala 编译器:检测纯/不纯函数

Man*_*oid 1 scala pure-function

在 Scala、Haskell 等 FP 语言中,使用了纯函数,这使得编译器可以优化代码。例如:

val x = method1()// a pure function call
val y = method2// another pure function call
val c = method3(x,y)
Run Code Online (Sandbox Code Playgroud)

由于method1method2是纯函数,因此评估彼此独立,编译器可以并行化这两个调用。

像 Haskell 这样的语言内部有结构(比如 IO monad),它告诉函数是纯函数还是执行一些 IO 操作。但是 Scala 编译器如何检测一个函数是纯函数呢?

Lev*_*sey 6

将代码块分类为纯代码块的一般方法是定义哪些操作是纯操作,并且由于纯操作是组合的,因此纯操作的组合是纯操作。

并行化实际上并不是纯代码更重要的好处之一:好处是可以使用任何评估策略。评估可以重新排序或结果可以缓存等。并行化是另一种评估策略,但没有很好地了解实际执行成本(并注意现代 CPU 和内存层次结构可能很难获得这种感觉),它通常会变慢相对于其他策略的事情下来。对于现代纯代码,懒惰和缓存重复值通常更有效,而并行性由开发人员控制(纯代码的一个好处是您可以在不改变代码语义的情况下对并行化方式进行任意更改) .

在 Scala 的情况下,编译器没有真正努力对纯/不纯代码进行分类,并且通常不会尝试替代评估策略:控制权留给程序员(该语言通过按名称调用和lazy) .

JVM 的 JIT 编译器可以并且确实在决定可以安全地内联和重新排序的内容时对字节码执行一些纯度分析。这不是特定val于 Scala 的,尽管最终局部变量(也称为Scala 中的local或finalJava 中的变量)启用了一些无法执行的优化。Javascript 运行时(对于 ScalaJS)可以(并且在实践中确实积极地这样做)同样地执行该分析,LLVM(对于 Scala Native)也是如此。