12

我是 Clojure 的新手。我是几个月前开始的。我正在尝试学习宏。

我最初对 Clojure 中宏和高阶函数之间的区别感到困惑,因为高阶函数可以接受 lambda,并根据任何条件和过滤器执行其中一个函数多少次。

因此,我在 StackOverflow 本身上发布了一个带有简单示例的问题。我从答案中清除了我的疑虑。

这是我理解的,

  • 与评估主体的函数不同,宏不会评估所有参数。
  • 宏可以选择评估什么和不评估什么,以及如何使用引用、取消引用和拼接语法将一段代码转换为另一段代码。
  • 然后评估来自宏的最终代码。

所以我的问题是,它与 C 中使用的预处理器指令和宏有什么不同?Lisp/Clojure 宏为开发人员提供了 C 宏完全缺乏且经常被广泛使用的功能。

4

3 回答 3

13

一些显着的差异:

  • Clojure 宏对Lisp 数据结构进行操作,而 C 宏对text进行操作。这种能力是Lisp同音异义的结果(即 Lisp 源代码表示为 Lisp 数据结构)。同调性对于宏观系统的有效性并不是绝对必要的,但它确实使它更加方便和自然。
  • 您可以在运行时和编译时执行 Clojure 宏(例如使用eval
  • Clojure 宏是用 Clojure 本身编写的。与 C 预处理器宏相比,它们有自己独立的迷你语言。在编写更复杂的宏时,这是一个很大的优势:您不必在不同语言之间进行心理切换(​​当然,您仍然需要在心理上区分处理宏时要执行的代码与要执行的代码生成为宏的输出)
  • Clojure 宏是图灵完备的——您可以在其中执行任意代码生成。对于标准 C 预处理器宏来说并非如此,它们在表达复杂代码生成的能力上有些受限。编辑:感谢 Jeremy 提供了一些有趣的技巧的链接,通过这些技巧可以强制 C 预处理器以完全转动的方式进行操作。但总体观点仍然存在:这些并不是编写通用代码的真正实用方法。

可以说,宏仍然是 Lisps 的显着“杀手级功能”。关于这个话题的一点额外解释,值得阅读 Paul Graham 的文章“ Lisp 的不同之处”

于 2013-07-08T12:13:44.053 回答
5

C 宏是纯文本重写宏。除了它们来自哪里之外,它们没有什么可怕的 C 语言——您可以在任何文本上使用 C 预处理器cpp(1) 。因此,使用 C 预处理器很容易生成非 C 形式,而且就 C 本身而言,您经常不得不跳过障碍来做相当琐碎的事情。因此, C 宏充满了陷阱

Clojure 宏是使用与常规 Clojure 函数不同的规则集执行的 Clojure 代码。它们不是接收评估的参数并返回结果,而是接收未评估的表单并返回一个表单,该表单最终可能在正常执行过程中被评估。

于 2013-07-08T14:31:42.267 回答
4

C 宏允许纯文本替换并且非常愚蠢(就可以执行的操作而言)。此外,如果它确实允许更复杂的表达式,那么使用它会很麻烦,因为您正在操作纯字符串。

由于 Clojure 和 Lisps 通常使用 S-Expressions(它们只是简单的链表)并允许在宏扩展时使用完整的语言,因此您可以构建更复杂和有用的表达式。

于 2013-07-08T12:13:37.333 回答