Tag Archives: lisp

The less familiar parts of Lisp for beginners — summary M

I’ve written a few posts about features of the Lisp language that a newcomer arriving from C++ might not have encountered.  I’m going through them alphabetically, so here is a summary page of the functions beginning with the letter M:

macro-function

macrolet

make-broadcast-stream

make-condition

make-dispatch-macro-character

make-instances-obsolete

make-load-form

make-load-form-saving-slots

make-method

make-package

make-symbol

makunbound

map

mask-field

method-qualifiers

muffle-warning

multiple-value-call

multiple-value-list

multiple-value-prog1

multiple-value-setq

 

The less-familiar parts of Lisp for beginners — multiple-value-setq

One more Lisp feature that newcomers might not have encountered is the multiple-value-setq macro.  While most introductions discuss multiple-value-bind, this feature is similar, but not always described.  The multiple-value-setq macro uses setq to store its values, rather than creating new bindings.  So, think of the relationship between setq and multiple-value-setq as being much like the relationship between let and multiple-value-bind.

The less-familiar parts of Lisp for beginners — multiple-value-prog1

Recently, our attention has been on Lisp features related to multiple values.  As mentioned previously, the values accessor allows the programmer to return zero or more values from a form, unlike C++ where a function can return at most one value.

Certain Lisp constructs encourage the use of progn, a feature that executes several forms in series and returns the values of the last form in the group.  Examples include if, unwind-protect, and any other feature that evalutes exactly one form in some context.  In that case, progn allows the programmer to collect several forms together and build a single form out of them for syntactic purposes.

One way that newcomers to Lisp can get tripped up is to think that prog1 or prog2 are exactly the same as progn, just returning the values from different forms in the series.  In fact, prog1 and prog2 return only the primary value of the corresponding form, they do not return all of the values.

If the programmer has a need to retrieve the multiple values from the first form in prog1, he or she should use multiple-value-prog1.  As suggested by the name, this special operator executes the forms inside it in order, and returns all values of the first form.

So, we’ve got progn, which returns all values.  We have prog1, which returns only the primary value, so we have multiple-value-prog1 to fill that gap.  We also have prog2 which, like prog1, does not return all values, but there isn’t a multiple-value-prog2.

Well, we can always write our own.  Here’s an example of a macro that achieves the effect of multiple-value-prog2:
 

(defmacro multiple-value-prog2 (&body body)
  `(progn
     ,(first body)
     (multiple-value-prog1
         ,@(rest body))))

Note that, with this macro, you get an error at macro expansion time if body does not contain at least two forms, but prog2 has the same behaviour, so I don’t consider that a bug in this macro.

Now, just for completeness, a transcript of some operations involving multiple values, also including the effect of that macro above:
 

CL-USER> (progn 
           (values 1 1) 
           (values 2 2) 
           (values 3 3))
3
3
CL-USER> (prog1
           (values 1 1) 
           (values 2 2) 
           (values 3 3))
1
CL-USER> (prog2
           (values 1 1) 
           (values 2 2) 
           (values 3 3))
2
CL-USER> (multiple-value-prog1
           (values 1 1) 
           (values 2 2) 
           (values 3 3))
1
1
CL-USER> (multiple-value-prog2
           (values 1 1) 
           (values 2 2) 
           (values 3 3))
2
2

The less-familiar parts of Lisp for beginners — multiple-value-list

Another variation for working with multiple values is multiple-value-list.  A newcomer to Lisp is likely to have encountered multiple-value-bind, which allows the individual returned values to be assigned to new variables, but may not have seen multiple-value-list.  This macro retrieves the values from a form and inserts them, in order, in a new list, which is then returned.

The less-familiar parts of Lisp for beginners — multiple-value-call

Continuing the series of less commonly-encountered Lisp features, multiple-value-call.  This function is much like funcall, but over multiple values.  If functions returning multiple values is unfamiliar to you, check the brief digression on the topic of values in this earlier post.

When funcall is invoked, if any of the arguments are forms, those forms are evaluated and the primary value is used in the function invocation.  Any additional values are discarded.  The multiple-value-call special operator captures all values returned by those forms and inserts them, in order, in the argument list before calling the function.  This is best illustrated with a simple example:
 

CL-USER> (funcall '+ (values 1 10) (values 1 20))
2
CL-USER> (funcall 'list (values 1 10) (values 1 20))
(1 1)
CL-USER> (multiple-value-call '+ (values 1 10) (values 1 20))
32
CL-USER> (multiple-value-call 'list (values 1 10) (values 1 20))
(1 10 1 20)