【发布时间】:2015-06-08 00:34:09
【问题描述】:
Set-macro-character 有一个名为 non-terminating-p 的可选参数。似乎是用来表示在读完宏字符后是否应该读另一个字符,但reader algorithm似乎忽略了这个参数。我设置为true还是false有区别吗?
【问题讨论】:
标签: macros common-lisp
Set-macro-character 有一个名为 non-terminating-p 的可选参数。似乎是用来表示在读完宏字符后是否应该读另一个字符,但reader algorithm似乎忽略了这个参数。我设置为true还是false有区别吗?
【问题讨论】:
标签: macros common-lisp
如果将non-terminating-p 设置为t,则宏字符可以在符号名称中以非转义形式出现(如符号foo#baz 中的#)。如果您将其保留为nil,并且读者在累积符号时遇到宏字符,则会终止该符号的集合(如foo'bar 中的',读作符号foo 和列表(quote bar)) .
请参阅阅读器算法中的第 8 步——有问题的参数在被视为 non-terminating macro character 和 terminating macro character 之间切换宏字符。
【讨论】:
一个例子,你会看到不同之处:
我们将使用两个不同的 Unicode 字符(这是使用 LispWorks)。 当这些字符被用作符号的一部分时,它变得很有趣。
(defun single-quote-reader (stream char) ; just an example, it won't be called
(declare (ignore char))
(list 'quote (read stream t nil t)))
(set-macro-character #\℅ #'single-quote-reader t) ; non-terminating
(set-macro-character #\℆ #'single-quote-reader nil) ; terminating
(defun test ()
(list (read-from-string "foo℅bar") ; non-terminating
(read-from-string "foo℆bar"))) ; terminating
CL-USER 21 > (test)
(FOO\℅BAR ; non-terminating
FOO) ; terminating
【讨论】:
其他答案解释了行为并给出了示例,但我认为值得指出并链接到规范。 HyperSpec 用于 set-macro-character 描述了 non-terminating-p 参数:
如果非终止-p 为真,char 变成non-terminating 宏字符;否则它变成一个terminating 宏字符。
相关词汇条目:
非终止 adj. (宏字符的)当它出现在扩展标记的中间时被视为组成字符。见Section 2.2 (Reader Algorithm)。
终止 n. (宏字符)是这样的,如果它在解析令牌时出现,它会终止该令牌。见Section 2.2 (Reader Algorithm)。
然后,正如m-n's answer 指出的,这里是阅读器算法的第八步:
此时正在累积令牌,并且遇到偶数个多个转义字符。如果在文件末尾,则进入第 10 步。否则,读取一个字符 y,并根据其语法类型执行以下操作之一:
如果 y 是组成或非终止宏字符:
- 如果 y 是一个带大小写的字符,它可能会被替换为相反大小写的对应字符,具体取决于当前 readtable 的 readtable 大小写,如第 23.1.2 节(Readtable Case 对 Lisp Reader 的影响)中所述)。
- Y 被附加到正在构建的令牌中。
- 重复第 8 步。
…
如果 y 是一个终止宏字符,则它终止令牌。首先字符 y 是未读的(参见 unread-char),然后进入第 10 步。
【讨论】: