Common Lisp No Dispatch Character Defined

544 Views Asked by At

I am currently reading the chapter on read-time macros from Paul Graham's "On Lisp" book.

The problem I am encountering is the following. When I run one of his examples:

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

I get the following error:

No dispatch function defined for #\’

Why is it happening? Could it be because I am running it at the REPL? What can one do to fix it?

1

There are 1 best solutions below

1
coredump On BEST ANSWER

The PDF from which you are copying the code uses punctuation marks outside the range of basic ASCII characters you are supposed to use here:

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

The usual quote symbol should instead use the apostrophe character:

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

The same goes for backquote:

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

You should be writing instead:

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

The #' is not necessary before lambda, since Common Lisp also defines a macro named lambda which expands into (function (lambda ...)).

You can test your new read macro as follows:

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

CL-USER> (funcall *)
10

When using SBCL, I obtain warnings about unused variables. This happens because the code declares variables in anonymous functions but never uses them. This is not a serious problem, but generally speaking, it is better to declare which variables are ignored:

(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)))))