Reader macros are a mechanism for extending the Common Lisp compiler that allows to addition or redefinition of custom syntax on the lexical levels.
One of the most significant problems of reader macros is the collision of dispatch characters.
I don't get why the language authors didn't take the same approach as with normal symbols – that is not, they didn't use the packages to resolve collisions.
The use of packages for conflict resolution gives the option to choose which syntaxes to use.
For example, such a simple implementation (I'm not entirely sure of its correctness but it seems to work) uses the symbols to pick the method for reading objects (with an example of how to use this method of reading lexical objects for clsql).
(eval-when (:compile-toplevel :load-toplevel)
(defun get-reader-function (symbol)
(let ((package (symbol-package symbol))
(name (symbol-name symbol)))
(symbol-function (find-symbol (format nil "~A-READER" name) package))))
(defun symbol-dispatch-reader (stream char arg)
(declare (ignore arg))
(let ((dispatch-symbol (read stream t nil t)))
(funcall (get-reader-function dispatch-symbol) stream char)))
(set-dispatch-macro-character #\# #\! #'symbol-dispatch-reader)
(defun sql-reader (stream char)
(declare (ignore char))
(let ((*readtable* (copy-readtable)))
(set-macro-character #\[ #'clsql-sys::sql-reader-open)
(set-macro-character #\] (get-macro-character #\)))
(read stream t nil t))))
And it's used like this:
(clsql:query #!sql [:select [*] :from :users])
I wonder if such a solution has any drawbacks.