The last time Hackerfall tried to access this page, it returned a not found error. A cached version of the page is below, or click here to continue anyway

ECL Quarterly - Volume II

Why we shouldn't use all these implementation-specific niceties

Lately, Zach Bane posted a nifty trick for accessing symbols from packages you're not in, literally:

foo::(list 'these 'symbols 'are 'from "foo" 'package)

It's nice, intuitive, practical and not compliant. It would be a minor problem, if it weren't a syntax hack, which is hard to implement portably as a library (at least I don't see any elegant solution). In my opinion it requires digging into implementation innards and tweaking the reader to support it. Manipulating strings before they are actually read is an option too. Also unlike the metaobject protocol, gray streams or extensible sequences it doesn't bring anything new to the table.

"But hey! It's just syntactic sugar for REPL interaction! Don't be such a grumpy guy!"

OK, fine, if you promise me that this "syntactic sugar" won't land in any library ever it's advertised after all. Nobody knows who will pick up this hint. And if critical mass will prevail, then this dubious syntactic sugar will become de-facto standard, so other implementations will be forced to implement it, or fail to load libraries using it.

Such a situation happened once. CLtL had an example of the LOOP usage, where a FOR clause landed after an UNTIL clause, which isn't ANSI compliant. The fact that it was supported by a few implementations lead to the situation imagined above.

If you really want some syntactic sugar for using other packages locally I propose a little uglier, yet portable, solution:

(defun sharp-l (stream char subchar)
  (declare (ignore char subchar))
  (let ((*package* (find-package (read stream))))
    (read stream nil nil t)))

(set-dispatch-macro-character #\# #\l #'sharp-l)

#l foo (list 'these 'symbols 'are 'from "foo" 'package)

It's only five lines of code and works everywhere (unless someone binds #l to his own reader macro). If someone wants to be a little fancier, then he may mimic the SLIME prompt in his syntax:

(defun sharp-x (stream char subchar)
  (declare (ignore char subchar))
  (let ((*readtable* (copy-readtable))
        (right #\))
        (rpar #\>))
    (set-macro-character rpar (get-macro-character right))
    (let ((*package* (find-package (read stream))))
      (peek-char #\> stream)
      (read-char stream)
      (read stream nil nil t))))

(set-dispatch-macro-character #\# #\[ #'sharp-x)

#[foo> (list 'these 'symbols 'are 'from "foo" 'package)

And, honestly I really like proposed syntax, but for my taste it's totally unportable and harmful for reasons I've mentioned above.

Continue reading on