Yesterday, I was compiling a function in SLIME, and I consistently got
error: illegal function call
messages from SBCL. The function was a
pretty complicated one, and I couldn't figure out the error. I even
resorted to commenting out sections, until I had an empty shell, with
only the docstring. Then realization dawned — here is a simplified
example of how the function looked like:
(defun foo (bar) "Docstring, followed by accidental dot". (let ((baz (1+ bar))) baz))
Did you notice the dot? I didn't, for a while (guess I should take breaks every hour or so and rest my eyes, especially in the evening). But the reader did.
Easily solved with a reader macro:
ReplyDelete(defconstant +string-escape+ #\\)
(defun revenge-string-reader-macro (stream delimiter)
(loop
:for ch = (read-char stream)
:until (char= ch delimiter)
:collect (if (char= ch +string-escape+)
(read-char stream)
ch) :into chars
:finally (let ((result (coerce chars 'string)))
(when (eql #\. (peek-char nil stream nil nil))
(warn "The revenge string reader macro detected a dot after the string ~S"
result))
(return result))))
(set-macro-character #\" (function revenge-string-reader-macro) nil)
C/USER[15]> '("abcl". d)
WARNING: The revenge string reader macro detected a dot after the string "abcl"
("abcl" . D)
C/USER[16]> '("abcl" . d)
("abcl" . D)
Thanks Pascal, but if I wanted a read macro for each idiotic mistake I make, I would soon run out of characters :-)
ReplyDelete