Package enhanced-multiple-value-bind
Description
Simply (:shadowing-import-from #:enhanced-multiple-value-bind #:
from your defpackage. Don't multiple-value-bind
)(:use)
!
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.
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:
lambda
, evaluate values forms, then "come back" for lambda
body);
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 multiple-value-bind
is invoked without apparent lambda list keywords (symbols beginning with "&"), then it simply expands to cl:multiple-value-bind
:
(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
:
(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.
Another example:
(multiple-value-bind
(x y &rest others)
(values 1 2 3 4)
(values (* x y) others))
→ 2, (3 4)
Simply (:shadowing-import-from #:enhanced-multiple-value-bind #:
from your defpackage. Don't multiple-value-bind
)(:use)
!
lambda-list values-form &body body => results
If lambda-list has no apparent lambda list keywords (symbols beginning with "&"),
then directly expand to a standard multiple-value-bind
with the same arguments.
Else, expand to `(multiple-value-call (lambda ,lambda-list ,@body) ,values-form)
.