Nice little trick du jour
This morning, I came up with a nice little trick which made my day. Perhaps this is already well known or even idiomatic, but in case it is not, it goes like this.
Sometimes, I have to read a whole Lisp file containing more than just one toplevel form and get the contents as an unprocessed list of expressions. This happens for instance when loading a DSL program that needs post-treatment.
Usually, I end up doing something like this:
(with-open-file (stream filename) (loop :for expr = (read stream nil :eof) :if (eq expr :eof) :return exprs :else :collect expr :into exprs)))
But for some reason, this has always felt clunky to me. I mean, instead of ogling the family jewels of this poor shy file, I should be able to read it as a whole (hint: read-delimited-list) and preserve its intimacy.
And then I realized that the only thing that prevents me from using read-delimited-list is the lack of an ending parenthesis. But as always, Common Lisp immediately comes to the rescue, this time with its rich streams API. The idea is that you can create a string stream that just contains the closing parenthesis, and concatenate this stream at the end of the file one. I can now do something like this instead:
(with-open-file (stream filename) (read-delimited-list #\) (make-concatenated-stream stream (make-string-input-stream ")"))))
Not only it is shorter, it also looks much more elegant to me.