From: Ron Garret on 3 Sep 2009 15:09 Just for the record, the design that I finally settled on as the Right Thing for symbol reader macros was this: (let ( (r (copy-readtable nil)) ) (defun read-symbol (stream) (let ( (*readtable* r) ) (read-preserving-whitespace stream)))) (defvar *enable-symbol-reader-macros* t) (defun symbol-reader-macro-reader (stream char) (unread-char char stream) (let ( (s (read-symbol stream)) ) (if *enable-symbol-reader-macros* (let ( (f (get s 'symbol-reader-macro)) ) (if f (funcall f stream s) s)) s))) (defun set-macro-symbol (symbol readfn) (setf (get symbol 'symbol-reader-macro) readfn) t) (map nil (lambda (c) (set-macro-character c 'symbol-reader-macro-reader t)) "ABCDEFGHIJKLMNOPQRSTUVWXYZ") This invokes the symbol reader macro only if the first letter of the symbol's name is actually entered as a capital letter. I ran into too many problems with symbol reader macros popping up where I didn't want them in legacy code when I didn't segregate the name space this way. There's also this related little hack: (defvar *enable-prefix-funcall-syntax* t) (defun prefix-funcall-syntax-reader (stream char) (unread-char char stream) (let ( (s (read-symbol stream)) ) (if (and *enable-prefix-funcall-syntax* ; Disable for #+foo(baz) (not (eql (symbol-package s) (find-package :keyword))) (eql (peek-char nil stream nil nil) #\()) (cons s (read stream)) s))) (map nil (lambda (c) (set-macro-character c 'prefix-funcall-syntax-reader t)) "abcdefghijklmnopqrstuvwxyz") This lets you write function calls using traditional f(x) syntax. It requires that there be no space between the function name and the open paren. So f(x) reads as (f x), but f (x) reads as two sexprs, f and (x). rg
|
Pages: 1 Prev: Let Over Lambda (ISBN 978-1-4357-1275-1) Next: Dave's difficulties with manual activities |