Set-dispatch-macro-character - don't eval the result
Posted: Sat May 14, 2011 8:48 am
Sorry if the title is vague. It's just the function name, which is a bit too long 
The problem: I'm trying to understand how set-dispatch-macro-character works, the code below doesn't have any other practical purpose, only for learning:
Now, what I wanted it to do:
I.e. I wanted it to create a list with sub-lists of two elements, instead, what happens is that if I later use this macro handler, it tries to evaluate the list as if it was a function call. So, for my example it would tell that I'm making illegal function call.
EDIT:
I actually did it like this:
But it doesn't feel right / I would be happy to know why it didn't work the first time.

The problem: I'm trying to understand how set-dispatch-macro-character works, the code below doesn't have any other practical purpose, only for learning:
Code: Select all
(set-dispatch-macro-character
#\# #\{
#'(lambda (first-char second-char stream)
(declare (ignore first-char))
(declare (ignore second-char))
(labels ((read-white (stream)
(loop for white-char = (read-char stream nil)
do (format t "reading white~&")
do (cond
((char= white-char +closing-curly+)
(return t))
((not white-char)
(return))
((not (find white-char +white+))
(unread-char white-char stream)
(return)))))
(read-key (stream)
(when (not (read-white stream))
(let ((result
(loop for key-char = (read-char stream nil)
do (when (or (find key-char +white+)
(char= key-char +colon+)
(not key-char))
(return (coerce token 'string)))
collect key-char into token)))
(read-white stream)
; This character must be column
; We should signal syntax error here, but
; for the purpose of this demo
; assume the input is always correct
(read-char stream nil)
(read-white stream)
result))))
(loop for key = (read-key stream)
do (format t "reading key: ~a~&" key)
do (when (not key) (return result-list)) ; This is what is being returned
collect (cons key (read stream))
into result-list))))
Code: Select all
#{ key : 42 }
; would create:
((key . 42))
EDIT:
I actually did it like this:
Code: Select all
(set-dispatch-macro-character
#\# #\{
#'(lambda (first-char second-char stream)
(declare (ignore first-char))
(declare (ignore second-char))
(labels ((read-white (stream)
(loop for white-char = (read-char stream nil)
do (format t "reading white~&")
do (cond
((char= white-char +closing-curly+)
(return t))
((not white-char)
(return))
((not (find white-char +white+))
(unread-char white-char stream)
(return)))))
(read-key (stream)
(when (not (read-white stream))
(let ((result
(loop for key-char = (read-char stream nil)
do (when (or (find key-char +white+)
(char= key-char +colon+)
(not key-char))
(return (coerce token 'string)))
collect key-char into token)))
(read-white stream)
; This character must be column
; If it's not, we should signal syntax error here, but
; for the purpose of this demo
; assume the input is always correct
(read-char stream nil)
(read-white stream)
result))))
(loop for key = (read-key stream)
do (format t "reading key: ~a~&" key)
do (when (not key)
(format t "about to return: ~a~&" result-list)
(return (list 'quote result-list)))
collect (cons key (read stream))
into result-list))))