Project author Jean-Philippe Paradis
Project type Library
Programming language Common Lisp
Status Ready-to-use
License Public Domain
Library type Wrapper macro
Project complexity Embarrassingly trivial
Latest release Version 1.0.1
Date 23 oct 2012
Quicklisp
(Nov 2012 dist and later)
Status Available
Version Latest
Depends on Depended on by
Directly Nothing
Indirectly Nothing Nothing

enhanced-multiple-value-bind provides an enhanced multiple-value-bind macro that adds support for lambda list keywords by expanding to a multiple-value-call when necessary. This makes catching multiple-value &rest and &key much more lightweight and convenient. A multiple-value-&bind alias is supported.

Some problems with writing out multiple-value-call with an inline lambda, especially with a big lambda body and trivial form arguments to multiple-value-call, compared to multiple-value-bind, are:

Multiple-value &rest and &key are currently not being used a lot (as far as I know), but the awkwardness of using them up to now might have something to do with this state of affairs. Their usefulness and convenience should now be reassessed.

If enhanced-mvb:multiple-value-bind is invoked without apparent lambda list keywords (symbols beginning with "&"), then it simply expands to cl:multiple-value-bind:

(enhanced-mvb:multiple-value-bind (a b c) (values 1 2 3)
  ...)
==
(multiple-value-bind (a b c) (values 1 2 3)
  ...)

Else, it simply expands to a multiple-value-call with inline lambda:

(enhanced-mvb:multiple-value-bind (a b &rest rest) (values 1 2 3)
  ...)
==
(multiple-value-call (lambda (a b &rest rest)
                       ...)
  (values 1 2 3))

An interesting consequence of this is that it's easy to accept an exact number of return values (though I'm not sure why you'd want to):

(multiple-value-bind (a b c &optional) (values 1 2 3 4))
error → "Invalid number of arguments: 4"

This follows the same principle as values in function type specifiers.

To use enhanced-multiple-value-bind, either refer to the provided multiple-value-bind directly:

;; A bit long...
(enhanced-multiple-value-bind:multiple-value-bind
      (x y &rest others)
    (values 1 2 3 4)
  (values (* x y) others))
→ 2, (3 4)

;; Much more managable package nickname.
(enhanced-mvb:multiple-value-bind (x y &rest others)
    (values 1 2 3 4)
  (values (* x y) others))
→ 2, (3 4)

Or (:shadowing-import-from #:enhanced-multiple-value-bind #:multiple-value-bind) in your defpackage (or with the package nickname, again). Don't (:use)!

enhanced-multiple-value-bind also exports multiple-value-&bind, with exactly the same functionality, so you can (:import-from #:enhanced-multiple-value-bind #:multiple-value-&bind) in your defpackage instead if you want.