set-macro-character 的非终止-p 参数有什么作用?

What does the non-terminating-p argument of set-macro-character do?

Set-macro-character has an optional argument called non-terminating-p. It seems to be used to indicate whether another character should be read after reading the macro character, but the reader algorithm 似乎忽略了这个论点。设置为真还是假有区别吗?

如果将 non-terminating-p 设置为 t,则宏字符可以在符号名称中显示为未转义(如符号 foo#baz 中的 #)。如果你离开它 nil 并且 reader 在累积符号时遇到宏字符,它会终止符号的收集(如 foo'bar 中的 ',它读作符号foo 和列表 (quote bar)).

参见 reader 算法中的第 8 步——所讨论的参数在被视为 non-terminating macro characterterminating 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 参数:

If non-terminating-p is true, char becomes a non-terminating macro character; otherwise it becomes a terminating macro character.

相关词汇条目:

non-terminating adj. (of a macro character) being such that it is treated as a constituent character when it appears in the middle of an extended token. See Section 2.2 (Reader Algorithm).

terminating n. (of a macro character) being such that, if it appears while parsing a token, it terminates that token. See Section 2.2 (Reader Algorithm).

然后,正如 指出的,这里是 reader 算法的第八步:

  1. At this point a token is being accumulated, and an even number of multiple escape characters have been encountered. If at end of file, step 10 is entered. Otherwise, a character, y, is read, and one of the following actions is performed according to its syntax type:

    • If y is a constituent or non-terminating macro character:

      • If y is a character with case, it might be replaced with the corresponding character of the opposite case, depending on the readtable case of the current readtable, as outlined in Section 23.1.2 (Effect of Readtable Case on the Lisp Reader).
      • Y is appended to the token being built.
      • Step 8 is repeated.
    • If y is a terminating macro character, then it terminates the token. First the character y is unread (see unread-char), and then step 10 is entered.