【问题标题】:Example of Sharpsign Equal-Sign reader macro?Sharpsign 等号阅读器宏的示例?
【发布时间】:2012-09-20 21:16:27
【问题描述】:

我见过这个用过一次,但不明白它的作用。参考资料说是

#n=object 读取任何以 object 作为其打印表示的对象。 但是,该对象由 n 标记,这是必需的 无符号十进制整数,以供语法#n# 参考。 标签的范围是最外层正在读取的表达式 打电话阅读;在此表达式中,可能不会出现相同的标签 两次。

在我看来,这只是 56 个随机选择的英语单词...请您举例说明何时可以使用它?

【问题讨论】:

  • #1=(programmable . #1#) on #lisp

标签: lisp common-lisp


【解决方案1】:

在 Common Lisp 中,它被阅读器和打印机使用。

这样,您可以在某个 s 表达式中标记一个对象,并在 s 表达式中的不同位置引用它。

标签是#someinteger=,后跟一个 s 表达式。整数必须是唯一的。您不能在单个 s 表达式中使用该标签两次。

对标签的引用是#someinteger#。整数标识要引用的 s 表达式。必须先引入标签,然后才能引用它。引用可以在一个 s 表达式中多次使用。

这例如用于读取和打印循环列表或具有共享数据对象的数据结构。

这里是一个简单的例子

? '(#1=(1 . 2) (#1#))

读作

((1 . 2) ((1 . 2)))

还要注意这一点:

? (eq (first *) (first (second *)))
T

这是一个相同的 cons 单元格。

让我们试试循环列表

确保打印机处理循环列表并且不会永远打印它们...

? (setf *print-circle* t)
T

现在我们正在构建一个列表:

? (setf l1 (list 1 2 3))
(1 2 3)

我们将最后一个 cdr 设置为第一个缺点:

? (setf (cdr (last l1)) l1)
#1=(1 2 3 . #1#)

正如你在上面看到的,打印出来的列表有一个标签,最后一个 cdr 是对该标签的引用。

我们也可以使用相同的符号直接输入一个循环列表。读者理解:

? '#1=(1 2 3 . #1#)
#1=(1 2 3 . #1#)

既然我们已经告诉打印机处理这样的结构,我们可以试试第一个例子中的表达式:

? '(#1=(1 . 2) (#1#))
(#1=(1 . 2) (#1#))

现在打印机检测到有两个对同一个 cons 对象的引用。

【讨论】:

  • read 是递归操作。在列表的情况下,( 是一个宏字符,递归读取直到)。最后一句话的意思是你不能在read中使用相同的标签,即'(#1=1 #1=2 #1#)是无效的,标签1在同一个最外层的读取调用中使用了两次。在加载或编译文件时,每个顶级表单都将在单独的最外层read 调用中读取,因此在不同的顶级表单中使用相同的标签没有问题,因为它们根本不相关。跨度>
  • Let Over Lambda 中还有一个关于循环表达式的部分:letoverlambda.com/index.cl/guest/chap4.html#sec_5
  • 我想你现在已经明白了,但是你引用的文字足以理解标签是什么。在#n= 中,n 是标签,一个无符号整数。散列后的数字(CLHS 中的尖号)通常是调度宏字符的参数。所以,它是一个介于#= 之间的数字用于标记,## 用于引用。在加载或编译的文件中,每个顶级表达式都是单独读取的,因此每个都是最外层的读取。在 REPL 中,通常每个提示都会启动最外层的读取。
猜你喜欢
  • 1970-01-01
  • 2011-09-19
  • 1970-01-01
  • 1970-01-01
  • 2012-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多