2

我目前正在阅读 Paul Graham 的“On Lisp”一书中关于读取时间宏的章节。

我遇到的问题如下。当我运行他的一个示例时:

(set-dispatch-macro-character #\# #\?
  #’(lambda (stream char1 char2)
    ‘#’(lambda (&rest ,(gensym))
       ,(read stream t nil t))))

我收到以下错误:

No dispatch function defined for #\’

为什么会这样?可能是因为我在 REPL 上运行它吗?可以做些什么来解决它?

4

1 回答 1

9

您从中复制代码的 PDF 使用的标点符号超出了您应该在此处使用的基本 ASCII 字符范围:

CL-USER> (char-name #\’)
"RIGHT_SINGLE_QUOTATION_MARK"

通常的引号应使用撇号字符:

CL-USER> (char-name #\')
"APOSTROPHE"

反引号也是如此:

CL-USER> (char-name #\‘)
"LEFT_SINGLE_QUOTATION_MARK"

你应该改写:

(set-dispatch-macro-character #\# #\?
                              #'(lambda (stream char1 char2)
                                `#'(lambda (&rest ,(gensym))
                                     ,(read stream t nil t))))

#'之前没有必要lambda,因为 Common Lisp 还定义了一个名为的lambda,它扩展为(function (lambda ...)).

您可以按如下方式测试新的读取宏:

CL-USER> #?10
#<FUNCTION (LAMBDA (&REST #:G617)) {1001C541FB}>

CL-USER> (funcall *)
10

使用 SBCL 时,我收到有关未使用变量的警告。发生这种情况是因为代码在匿名函数中声明了变量,但从不使用它们。这不是一个严重的问题,但一般来说,最好声明哪些变量被忽略:

(set-dispatch-macro-character
 #\# #\?
 (lambda (stream &rest chars)
   (declare (ignore chars))
   (let ((rest (gensym)))
     `(lambda (&rest ,rest)
        (declare (ignore ,rest))
        ,(read stream t nil t)))))
于 2018-04-05T16:18:38.963 回答