Skip to main content

make-dispatch-macro-character

make-dispatch-macro-character Function

Syntax:

make-dispatch-macro-character char &optional non-terminating-p readtable → t

Arguments and Values:

char—a character .

non-terminating-p—a generalized boolean. The default is false.

readtable—a readtable. The default is the current readtable.

Description:

make-dispatch-macro-character makes char be a dispatching macro character in readtable.

Initially, every character in the dispatch table associated with the char has an associated function that signals an error of type reader-error.

If non-terminating-p is true, the dispatching macro character is made a non-terminating macro character ; if non-terminating-p is false, the dispatching macro character is made a terminating macro character .

Examples:

(get-macro-character #\\{) → NIL, *false* 
(make-dispatch-macro-character #\\{) → T
(not (get-macro-character #\\{)) → false
The *readtable* is altered.

See Also:

*readtable*, set-dispatch-macro-character

Expanded Reference: make-dispatch-macro-character

Creating a dispatch macro character

make-dispatch-macro-character designates a character as a dispatching macro character. After calling it, you can define sub-characters using set-dispatch-macro-character.

(let ((*readtable* (copy-readtable)))
;; Make ! a dispatch macro character
(make-dispatch-macro-character #\!)
;; Verify it is now a macro character
(not (null (get-macro-character #\!))))
=> T

Defining sub-character handlers

After making a character a dispatch character, use set-dispatch-macro-character to assign behavior to sub-characters. The dispatch function receives the stream, the sub-character, and the optional numeric argument.

(let ((*readtable* (copy-readtable)))
(make-dispatch-macro-character #\!)
(set-dispatch-macro-character #\! #\k
(lambda (stream sub-char arg)
(declare (ignore sub-char arg))
(let ((sym (read stream t nil t)))
(list 'keyword sym))))
(with-input-from-string (s "!kfoo")
(read s)))
=> (KEYWORD FOO)

Terminating vs. non-terminating dispatch characters

By default, make-dispatch-macro-character creates a terminating macro character. Pass t for non-terminating-p to make it non-terminating, meaning it can appear within a symbol token without ending it.

(let ((*readtable* (copy-readtable)))
;; Terminating (default): ends a token
(make-dispatch-macro-character #\! nil)
(set-dispatch-macro-character #\! #\t
(lambda (s c a) (declare (ignore s c a)) :bang))
(with-input-from-string (s "abc!tdef")
(list (read s) (read s))))
=> (ABC :BANG)
;; Note: "def" is still in the stream as a separate token

The # character is a built-in dispatch macro character

The standard # character is already a dispatching macro character in the standard readtable. You do not need to call make-dispatch-macro-character on it; you can directly use set-dispatch-macro-character to add or modify sub-character handlers.

;; # is already a dispatch macro character
(let ((*readtable* (copy-readtable)))
(set-dispatch-macro-character #\# #\!
(lambda (stream sub-char arg)
(declare (ignore sub-char arg))
(list 'shebang (read stream t nil t))))
(with-input-from-string (s "#!test")
(read s)))
=> (SHEBANG TEST)