18

我正在尝试了解 Lisp 中到目前为止我还没有使用多少的部分。读取宏目前引起了我的注意。没有关于它们使用的大量信息,这将有助于了解人们对它们做了什么,既可以获取它们如何工作的示例,也可以了解它们可以解决哪些类型的问题。在此之后,是否有任何指导方针可以了解什么是读取宏的好坏使用?

4

7 回答 7

20

S 表达式是 Lisp 用于 Lisp 数据的语法。S 表达式使用函数 READ 读取,读取宏是 Lisp 扩展读取器的内置方式。这意味着读取宏最直接的用途是实现预定义的数据语法,并开辟了改变或扩展 Lisp 读取 s 表达式的方式的可能性。

Lisp 为许多数据类型提供了预定义的外部语法:符号、数字、字符串、数组、字符、conses、列表、结构等等。它允许打印和回读数据对象。

  1. Lisp 缺少其他几种数据类型的语法——主要是哈希表和 CLOS 对象。因此,在用户代码中第一次使用读取宏将是扩展阅读器,使其能够读取数据结构,如哈希表、并行向量、新数字类型……基本上,开发人员希望每种数据类型都有一个外部语法可以回读。

  2. 由于 Lisp 也对代码使用 s 表达式,读取宏的第二个用途是扩展 Lisp 程序的符号。一个典型的例子是使用 [ 和 ] 来编写嵌入式 SQL 代码。通常的 Lisp 语法看起来很相似,但是 [ and] 的使用有助于 SQL 表达式在代码中脱颖而出。另一个例子是使用读取宏为嵌入式编程语言提供标识符,如 Objective C 常量、消息等。Clozure CL 使用它来表示区分大小写/保留大小写的标识符,并在读取期间使用索引查找它们的定义外部可用的标识符。

  3. 第三个用途是将不同的语法嵌入到 Lisp 语法中。一个旧的例子是中缀读取宏,它允许嵌入中缀表达式。其他示例是嵌入式 HTML 或 XML 语法,或其他编程语言语法的嵌入式片段。

  4. 有时读取宏用于实现其他(相关)语言,这些语言使用不同于预定义的 Common Lisp 语法的 s-expression 语法。一个例子是 Scheme s-expressions 的阅读器——它与 Common Lisp 略有不同。

于 2009-08-29T18:38:17.687 回答
7

当您可能想要拥有文字对象的语法时,将使用阅读器宏。它们的唯一问题是可能的语法的平面命名空间(但是,有一些方法可以解决这个问题)。阅读器宏的用法并不多。我想到的一些例子是:

于 2009-08-29T18:32:46.497 回答
4

实际上,对于我的普通 Lisp 代码,我倾向于避免使用它们。最近,我什至发现自己拒绝了第三方库,因为它使用了阅读器宏。这主要是因为与符号不同,阅读器宏只有一个“命名空间”。在选择合适的调度角色时,我似乎经常不同意图书馆作者的品味。

但是,我使用自定义的非标准 readtables + read成功完成了简单的解析任务。到目前为止,我使用自定义readtable实现的最复杂的解析器是一个 HTML 模板引擎(另一个,抱歉),其语法类似于 JSP/ASP,但使用 Common Lisp 作为实际的模板语言,所以你可以拥有类似的东西

<% (for (title . link) in breadcrumb do %><a href="<%= link %>"><%= title %></a><% ) %>

(不过,并非仅使用可读 hacks 完成,代码必须经过预处理阶段)。

于 2009-08-29T18:05:44.087 回答
2

虽然我使用了很多宏,但我从来没有发现需要使用读取宏,除了随意的实验。如果有帮助,请在“Let Over Lambda”上找到关于它们的广泛讨论:http: //letoverlambda.com/index.cl/toc

于 2009-08-29T17:48:38.427 回答
2

我在 Github 上有两个小项目,展示了如何以及为什么要在 Common Lisp 中使用阅读器宏。它们是SHELLSHOCKBOXEN。正如其他答案中提到的,CL-INTERPOL是一个杰出且有用的例子。

这些是否是阅读器宏的良好用途显然是主观的,但我肯定认为它们很有用,否则我不会编写代码!

于 2011-05-20T07:34:41.513 回答
1

可以嵌入读取宏的一种特别常见且有用的替代语法是正则表达式语法。实现它一点也不难,因为它只是读取具有不同转义规则的字符串,但如果你经常使用正则表达式,它真的可以得到回报。dmitry-vk 提到的CL-INTERPOL库提供了此功能以及许多其他功能。

于 2009-08-31T13:27:14.737 回答
0

请参阅Vsevolod Dyomkin 对我的问题Writing Common Lisp code that executes from the command line, but not inside the interpreter的回答,这是阅读器宏的应用程序。

于 2012-03-22T15:19:24.923 回答