In learning Common Lisp I come across some pretty esoteric stuff (Lisp is like that). I tend to learn a language from specification-like documents. One thing this does is give me a view of the language that is probably different from how a typical programmer in that language sees it. It’s difficult for me to get a pragmatic view of the language. In Lisp for example, do people use
PROG (as opposed to
TAGBODY)? What is the value of
(VALUES)? How often do people put a reader macro on
!? And, the subject of this post, does anyone ever use
Well, I turned to a co-worker who gets paid to program in Lisp. He said, “Yes, it’s quite often used in macros”; he turned to his current project and found 5 uses of it, all in macros. It turns out that 2 of those uses were buggy (I never did get paid for improving the quality of that project). I was tempted to humourously advertise
MULTIPLE-VALUE-PROG1 with a strapline: “Causes experts to write buggy code 40% of the time”. A typical use is when you have a macro that takes a body (list of forms), where the expansion of the macro executes the body, and then does some more stuff (cleanup perhaps), but wants to pretend that really it’s just the the body that being executed, so the resulting form will yield the same values that the body alone does.
You can’t use just a
PROGN like this:
(defmacro foo (... &body body) (progn ,@body (more-stuff ...)))
PROGN won’t return the values from the body, it’ll return values from more-stuff. Combining
PROGN gives the almost right:
(defmacro foo (... &body body) (prog1 (progn ,@body) (more-stuff ...)))
but it goes wrong when body returns other than exactly 1 value; it’s not multiple value transparent in other words. That’s why you need
(defmacro foo (... &body body) (multiple-value-prog1 (progn ,@body) (more-stuff ...)))
The bug is when you forget the inner
(defmacro foo (... &body body) (multiple-values-prog1 ,@body (more-stuff ...)))
This returns multiple values, but unfortunately it returns all the values from the first form of body, not its last form. In the, probably all too common, case where body has only one form, you won’t spot the difference and this bug might go unnoticed for some while.
The amusing icing on the cake is that you can use Google’s codesearch facility to find bugs like this automatically: search for “multiple-value-prog1 ,@”. When I searched I got three results. The first result is a correct implementation of a
MULTIPLE-VALUE-PROG2 macro, the other 2 are bugs. The code for the first bug is:
(defmacro waiting-for-token-event ((contact &optional (token-data 0)) &body body) `(multiple-value-prog1 ,@body (await-token-event ,contact ,token-data)))
Now you know what to look for you should be able to see how this follows the typical use pattern outlined above, and is also not correct.
multiple-value-prog1 alone shows that most of the time this appears in Lisp code it is either to describe how to format
MULTIPLE-VALUE-PROG1 forms in a pretty printer or code indenter or similar, or it appears in a compiler test suite. There aren’t very many actual uses of it. Well, that’s the impression I get when viewing the world through Google’s codesearch spectacles.