Macros are a common part of Lisp languages, and one of their most lauded features. Much research has gone into making macros both safer and more powerful resulting in developments in multiple areas, including maintaining hygiene, and typed program staging. However, macros do suffer from various downsides, including being second-class. Particularly egregious for eager functional programming, they are unable to be passed to higher-order functions or freely composed. Fexprs, as reformulated by John Shutt, provide a first-class and more powerful alternative to macros that meshes well with pure functional programming. Unfortunately, naive execution of fexprs is much slower than macros due to re-executing unoptimized operative combiner code at runtime that, in a macro-based language, would have been expanded and then optimized at compile time. To show that fexprs can be practical replacements for macros, we formulate a small purely functional fexpr based Lisp, Kraken, with an online partial evaluation and compilation framework that supports first-class, partially-static-data environments and can completely optimize away fexprs that are used and written in the style of macros. We show our partial evaluation and compilation framework produces code that is more than 70,000 times faster than naive interpretation due to the elimination of repeated work and exposure of static information enabling additional optimization. In addition, our Kraken compiler performs better compared to existing interpreted languages that support fexprs, including improving on NewLisp's fexpr performance by 233x on one benchmark.
翻译:摘要:宏是 Lisp 语言常见的一部分,也是它最受推崇的特性之一。为使宏更加安全和强大,进行了大量的研究,这些研究在多个方面开展,例如保持卫生、类型化程序分段等。 然而,宏也存在不少缺点,其中包括作为二等民族。对于热切的函数式编程,这尤其令人不满,因为他们无法传递给高阶函数或自由组合。由 John Shutt 重新制定的 Fexprs 为宏提供了第一类和更强大的替代方案,与纯函数式编程很好地融合。不幸的是,由于在运行时重新执行未优化的操作组合器代码,与基于宏的语言中所展开并在编译时优化的代码相比,Fexprs 的天真执行速度要慢得多。为了展示 Fexprs 可以成为宏的实用替代品,我们制定了一种基于 Fexprs 的小型纯函数 Lisp,Kraken,它具有在线部分求值和编译框架,支持第一类、部分静态数据环境,并且可以完全优化掉使用和以宏风格编写的 fexprs。我们展示了我们的部分求值和编译框架生成的代码比天真解释快 70,000 多倍,因为消除了重复的工作并暴露了静态信息,从而实现了更多的优化。此外,我们的 Kraken 编译器与支持 fexprs 的现有解释语言相比表现更佳,其中在一项基准测试中 NewLisp 的 fexpr 性能提高了 233 倍。