代码之家  ›  专栏  ›  技术社区  ›  MadPhysicist

公共Lisp未定义分派字符

  •  2
  • MadPhysicist  · 技术社区  · 7 年前

    我目前正在阅读保罗·格雷厄姆(PaulGraham)的《论Lisp》一书中关于阅读时间宏的章节。

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

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

    我得到以下错误:

    No dispatch function defined for #\’
    

    为什么会这样?可能是因为我在REPL运行它吗?我们能做些什么来修复它?

    1 回复  |  直到 7 年前
        1
  •  9
  •   coredump    7 年前

    从中复制代码的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 ,因为公共Lisp还定义了 已命名 兰姆达 扩展为 (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)))))
    
    推荐文章