Reader Macros: A cool feature, frustration waiting to happen

One of the neat features in Common Lisp is that any program can register a new reader macro that will read from the input stream when it sees some character. A good example of where this is useful and well implemented is Edi Weitz’s :cl-interpol.  This library allows you to, for any given file, declare that you want to read phrases that begin with #? as a interpolated.

For example:
#?"${name} is coming over for ${event}"
#?/\d{3}(-|\.|\s)\d{3}(-|\.|\s)\d{4}/ ;creates a regular expression

This can be a wonderful time saver and can be quite a bit easier on the eyes than a serious format.  However, these reader syntaxes can be good and bad.  Many library authors include them by default and they are enabled when the package is loaded.  The reader syntaxes are not bound by packages (because the readtable is global).  This has the downside of your code randomly ceasing to work based on some vagary of library load order and which reader syntax you expect to be enabled.

I had problems when loading LISA into an application for the first time because it stomped my :cl-interpol file-level reader declaration and kept stomping it.  No amount of reevalution seemed to provide reliable results as to which of the two syntaxes were enabled.  I finally found where in the LISA config to disable that syntax, which allowed me to work around the conflict.

I had a similar experience when trying to use :cl-mediawiki in a project for the first time.  CL-MediaWiki used to use of the :cl-unification #T reader macro which enabled a template engine to ease unification.   (Now it uses the make-template function).  When I added cl-mediawiki to my projects dependancy list and started to use it, it failed utterly.  The reason? Apparently Closure-HTML has a reader syntax defined and enabled for #T.  Both of these libraries add this syntax as part of their standard load.  This leaves the end user completely unable to use your library (or forcing them to patch it) if it stomps on existing reader-syntaxes that they have enabled.

My suggesstion would be to follow Edi’s example and allow the end user to enable a syntax on a perfile level (at least) and have the syntaxes disabled by default.  This allows the user to decide when and where they use your handy syntax without frustrating them along the way. Also as best I can tell, following Edi’s example is always safe and good advise.

Leave a Reply

Your email address will not be published. Required fields are marked *