为什么用函数式语言编写编译器更容易?

时间:2010-05-25 15:26:23

标签: compiler-construction haskell ocaml functional-programming

我一直在考虑这个问题很长时间,但实际上无法在Google上找到答案以及Stackoverflow上的类似问题。如果有重复,我很抱歉。

很多人似乎都说用OCaml和Haskell等函数式语言编写编译器和其他语言工具比用命令式语言编写它们更有效,更容易。

这是真的吗?如果是这样的话 - 为什么用函数式语言而不是像C这样的命令式语言来编写它们是如此高效和容易?另外 - 在函数式语言中,语言工具不是像C语言这样的低级语言慢吗?

7 个答案:

答案 0 :(得分:99)

编译器通常会对树有很多工作。源代码被解析为语法树。然后可以将该树转换为具有类型注释的另一个树以执行类型检查。现在,您可以将该树转换为仅包含核心语言元素的树(将类似糖的符号表示为未加工的形式)。现在,您可以执行基本上在树上进行转换的各种优化。之后,您可能会以某种正常形式创建一个树,然后遍历该树以创建目标(汇编)代码。

功能语言具有模式匹配和对高效递归的良好支持等功能,这使得使用树很容易,因此它们通常被认为是编写编译器的好语言。

答案 1 :(得分:38)

许多编译器任务是树结构上的模式匹配。

OCaml和Haskell都具有强大而简洁的模式匹配功能。

向命令式语言添加模式匹配更加困难,因为正在评估或提取的任何值以匹配模式必须是无副作用的。

答案 2 :(得分:15)

要考虑的一个重要因素是,任何编译器项目的很大一部分就是当你可以自我托管编译器并“吃你自己的狗粮”时。因此,当您查看OCaml等语言研究语言时,它们往往具有编译器类型问题的强大功能。

在我上一次编译器式的工作中,我们在操作C代码时正是出于这个原因使用了OCaml,它只是该任务的最佳工具。如果INRIA的人们已经建立了具有不同优先级的OCaml,那么它可能不太合适。

也就是说,函数式语言是解决任何问题的最佳工具,因此从逻辑上讲它们是解决这一特定问题的最佳工具。 QED。

/ me:快点回到我的Java任务......

答案 3 :(得分:8)

基本上,编译器是从一组代码到另一组代码的转换 - 从源到IR,从IR到优化的IR,从IR到汇编等。这正是函数式语言的设计 - a纯粹的功能只是从一件事转变为另一件事。势在必行的功能没有这种品质。虽然您可以用命令式语言编写这种代码,但函数式语言专门用于它。

答案 4 :(得分:6)

另见

F# design pattern

FP按操作'分组',而OO按类型'分组','按操作'对编译器/解释器更自然。

答案 5 :(得分:6)

一种可能性是编译器倾向于非常谨慎地处理大量的极端情况。通过使用以与其实现的规则相似的方式构造实现的设计模式,通常可以更轻松地获得正确的代码。通常最终会成为声明式(模式匹配,“何时”)而不是命令式(排序,“何时”)设计,因此更容易在声明性语言中实现(并且大多数都是功能性的)。

答案 6 :(得分:4)

似乎每个人都错过了另一个重要原因。为解析器编写嵌入式域特定语言(EDSL)非常容易,它在普通代码中看起来很像(E)BNF。像Parsec这样的 Parser组合器使用高阶函数和函数组合很容易用函数式语言编写。不仅容易,而且非常优雅。

基本上,您只需将函数表示为最简单的通用解析器,并且您具有特殊操作(通常是高阶函数),这使您可以这些原始解析器组合成更复杂,更具体的语法解析器

这不是当然做削皮框架的唯一方法。