我和几个朋友正在开发一个新平台,我们希望用lisp语言进行构建。其中最主要的吸引点是宏(macros)功能。我们都使用Common Lisp,但我想尝试Clojure。
当我提出这个想法时,他们中的一个人说Clojure的宏系统“更弱”。我想知道这是不是真的,并在哪些领域上表现较弱。
我和几个朋友正在开发一个新平台,我们希望用lisp语言进行构建。其中最主要的吸引点是宏(macros)功能。我们都使用Common Lisp,但我想尝试Clojure。
当我提出这个想法时,他们中的一个人说Clojure的宏系统“更弱”。我想知道这是不是真的,并在哪些领域上表现较弱。
他们在功能上基本相当,即:
现在来看一些区别:
Common Lisp还允许使用读取宏,这使您可以更改读取器的行为。这允许您引入全新的语法(例如用于数据结构字面量)。这可能是您的朋友将Clojure的宏系统描述为“较弱”的原因,因为Clojure不允许读取宏。在Clojure中,您基本上只能使用(macro-name ....)
这种语法,但除此之外,您可以做任何想做的事情。对于读取宏是否好的看法不一:我的个人观点是不好,因为它不会给您带来任何额外的“力量”,并且有可能导致极度混乱。+
可以分别定义为clojure.core/+
和my.vector.library/+
,在你自己的命名空间中,你可以use另一个命名空间的定义,这意味着你可以根据需要从clojure.core
或my.vector.library
中选择+
。{}
和向量[]
有额外的字面量。这给你比传统的Lisp表达式更多的表达能力(在简洁易读的语法方面)。特别地,用[]来绑定形式是Clojure中的惯例,我认为这对于宏和普通代码都很有效——它让它们与其他括号清晰地区分开来。总体而言,差异相对较小。我认为Clojure更简单、更优雅,而Common Lisp具有一些额外的功能(自行决定使用风险!)。两者都非常强大,因此选择任何一个都不会错。
clojure.core/+
和 my.vector.library/+
相当于 cl:+
和 my.vector.library:+
。在 Common Lisp 中,您可以使用 import-from
和 shadow
从任何包中导入和隐藏符号,包括 cl
。 - Vsevolod Dyomkin[1 2 3 4]
这样声明向量的语言在功能上与声明为 (vector 1 2 3 4)
或者 #{1,2,3,4}#
的语言完全相等。你可能会认为其中一种比其他方式更加“表达性”,但这是主观的。另一方面,如果你不能在没有显式循环的情况下填充向量,那么从客观意义上讲,你的语言就缺乏了能力——它根本没有提供声明向量字面量的结构。这两件事情是根本不同的。我坚信保罗·格雷厄姆谈到的是后者意义上的能力,而不是化妆性的语法选择。 - mikera关于普通宏,Lisp和Clojure的变体之间有以下不同:
因此,总体而言,Lisp的方法更加粗糙,但更加灵活。Clojure的宏可能稍微更容易上手,但当你超越简单的语法修改并开始定义完整的DSL时,使用起来会更加困难。
关于阅读器宏,如您所知,Clojure不向用户提供此选项,而CL则提供。因此,在CL中,阅读器宏发现了许多用途,例如字符串插值、国际化支持、SQL DSL或Java交互。更不用说大量特殊情况,当阅读器宏可以用于帮助创建高级DSL时。
Clojure宏有一些优点:
~'it
来捕获未经限定的符号 it。所以 Paul Graham 的 aif 是(defmacro aif [test true-fm & [false-fm]]
\
(let [~'it] ~true-fm ~false-fm))` - Riley也许你的朋友指的是Clojure宏系统在某种意义上比较“弱”,因为Clojure目前不支持“读取器宏”,但这并不意味着宏系统更弱,因为据我所知,读取器宏可能会使事情变得非常复杂。
我也不建议你将宏作为主要吸引点。它们很强大,但当你被某种特定技术所吸引时,即使有更简单的技术可用(在宏的情况下,更简单的技术是函数),你也会开始到处应用它。
另一个你应该考虑的重要事情是你想要针对的“平台”,因为Clojure支持JVM,并且还有所有适用于JVM平台的工具。