【问题标题】:What is the difference between "regular" and "reader" macros?“常规”和“阅读器”宏有什么区别?
【发布时间】:2017-10-22 04:08:23
【问题描述】:

我对 Clojure 比较陌生,无法完全理解阅读器宏常规宏之间的差异,以及差异为何如此显着。

在什么情况下你会使用其中一种,为什么?

【问题讨论】:

    标签: clojure macros


    【解决方案1】:

    阅读器宏以普通宏无法做到的方式更改语言的语法(例如,@foo 变成 (deref foo))(普通宏无法去掉括号,所以你必须做类似(@ foo)) 的事情。它被称为 reader 宏,因为它是在 repl 的 read 传递中实现的(查看 source)。

    作为 clojure 开发人员,您只会创建 常规 宏,但会使用大量阅读器宏,而不必明确考虑它们。

    阅读器宏的完整列表在这里:https://clojure.org/reference/reader,包括常见的东西,如@',和#{}

    Clojure(与其他一些 lisps 不同)不支持用户定义的阅读器宏,但通过 tagged literals(例如 #inst#uuid)在阅读器中内置了一些可扩展性

    【讨论】:

      【解决方案2】:

      tl;dr*

      宏 [普通宏] 在求值期间扩展(R​​EPL 的 E),与符号相关联,对 lisp 对象进行操作,并出现在表单的第一个或“函数”部分中。 Clojure 和所有 lisps 都允许定义新的宏。

      Reader 宏在读取期间运行,在求值之前,是单个字符,对字符串进行操作,在所有 lisp 对象从 reader 发出之前,并且不限于在第一个或“函数”中,表格的一部分。 Clojure 与其他一些 lisps 不同,它不允许定义新的阅读器宏,除非编辑 Clojure 编译器本身。

      更多词:

      普通的非阅读器宏,或者只是“宏”,对 lisp 对象进行操作。考虑:

      (and 1 b :x)

      and 宏将使用两个值调用,一个值是 1,另一个是由符号 b(不是 b 的值)和关键字 :x 组成的列表。 and 宏正在处理的所有内容都已经是一个 lisp (Clojure) 值。

      宏扩展仅在宏位于列表开头时发生。 (and 1 2) 扩展了 and 宏。 (list and) 返回错误,“Can't take value of a macro”

      阅读器负责将字符串转换为在 Clojure 中,阅读器宏是单个字符,它改变阅读器(负责将文本流转换为 lisp 对象的部分)的操作方式。 Clojure 的 lisp 阅读器的调度位于 LispReader.java。正如 Alejandro C. 所说,Clojure 不支持添加阅读器宏。

      阅读器宏是一个字符。 (我不知道这是否适用于所有 lisps,但 Clojure 当前的实现只支持单字符阅读器宏。)

      阅读器宏可以存在于表单中的任何位置。考虑(conj [] 'a),如果' 宏是正常的,则tick 需要成为一个lisp 对象,因此代码将是符号conj、空向量、符号' 以及最后的符号@ 的列表987654336@。但是现在评估规则将要求 ' 自行评估。相反,读者在看到 ' 时会包装完整的 s-exp,然后是 quote,因此返回给评估器的值是 conj 的列表、一个空向量和 quote 的列表通过a。现在quote 是列表的头部,可以更改它引用的评估规则。

      【讨论】:

        【解决方案3】:

        简短地说,阅读器宏是一个低级功能。这就是为什么他们很少(只是@,退出等等)。拥有许多阅读规则会使任何语言变得一团糟。

        常规宏是 Clojure 中广泛使用的一种工具。作为开发人员,如果您不是 Clojure 核心开发人员,欢迎您编写自己的常规宏,但不要编写阅读器宏。

        您可以始终使用自己的标记文字来替代阅读器规则,例如 #inst "2017" 会给您一个 Date 实例等等。

        【讨论】:

          猜你喜欢
          • 2011-01-26
          • 1970-01-01
          • 2011-09-17
          • 2016-06-08
          • 1970-01-01
          • 2019-09-10
          • 1970-01-01
          • 1970-01-01
          • 2014-03-24
          相关资源
          最近更新 更多