【问题标题】:How are Clojure macros different from C macros?Clojure 宏与 C 宏有何不同?
【发布时间】:2013-07-08 12:03:19
【问题描述】:

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

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

所以我在 StackOverflow 上发布了一个 question 并附有一个简单的例子。 我从答案中消除了我的疑虑。

这是我理解的,

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

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

【问题讨论】:

    标签: clojure


    【解决方案1】:

    一些显着的差异:

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

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

    【讨论】:

    • 其实你可以拥有一个没有同音性的完整宏系统。用于表示代码的数据结构只是比 Lisp 数据结构具有更复杂的形状。参见例如Scala macros
    • 另一件事是您列出的属性的结果,但应该作为单独的一点列出,那就是使用 Clojure 宏很容易创建新的控制结构(条件形式、循环、 ... 表单等),然后可以使用正常的 Clojure 语法。
    • @JeremyW.Sherman 你可能认为 C 宏图灵完备,但仍然不可能对它们进行任意转换(即使你想做多少遍),我认为这是更多很重要的一点。例如,您不能编写宏 M,使 M(f(x)) 扩展为 f(x,y)g(x)
    • @sepp2k 是的,但人们常常把图灵完备性视为高标准。有大量非常丑陋的低级语言有意或半无意地展示了图灵完备性。作为一种实用的通用编程语言是完全不同的事情。 :)
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 2012-03-25
        • 1970-01-01
        • 2019-11-18
        • 2018-11-19
        • 2010-11-21
        • 2015-11-16
        • 2012-11-19
        • 2019-03-31
        • 1970-01-01
        相关资源
        最近更新 更多