Nyquist / XLISP 2.0  -  Contents | Tutorials | Examples | Reference

cl:multiple-value-bind


The cl:multiple-value-bind macro creates new bindings for a list of symbols and evaluates expressions that use these bindings:

(cl:multiple-value-bind symbols values [expr1 ...])
symbols - a list of symbols
values - a Lisp expression returning one or more values
exprN - arbitrary Lisp expressions
returns - the value[s] returned by the last expression

(defmacro cl:multiple-value-bind (symbols expr &rest body)
  (and (or (not (consp symbols))
           (eq 'quote (first symbols))
           (dolist (symbol symbols)
             (or (symbolp symbol) (return t))))
       (error "not a list of symbols" symbols))
  (setq cl:*multiple-values* nil)
  (let* ((result (eval expr))
         (values (if cl:*multiple-values*
                     *rslt*
                     (list result)))
         (number-of-symbols (length symbols))
         (number-of-values  (length values))
         (bindings nil))
    (dotimes (index number-of-symbols)
      (push (if (< index number-of-values)
                (list (nth index symbols)
                      (list 'quote (nth index values)))
                (nth index symbols))
            bindings))
    (setq bindings (reverse bindings))
    `(let ,bindings ,@body)))

The 'values' expression is evaluated, and each of the symbols is bound to the respective value returned by the evaluation. If there are more symbols than values returned, extra values of NIL are bound to the remaining symbols. If there are more values than symbols, the extra values are ignored. The symbols are bound to the values by let, behaving like an implicit progn.

Before evaluating 'expr1', the cl:*multiple-values* variable is  T  if evaluating the 'values' expression returned multiple values and NIL with a normal return value.

The cl:multiple-value-bind macro binds multiple values to local let variables::

> (macroexpand-1 '(cl:multiple-value-bind (a b c)
                      (cl:values 1 2 3)
                    (list a b c)))
(LET ((A (QUOTE 1))
      (B (QUOTE 2))
      (C (QUOTE 3)))
  (LIST A B C))

The quotes are necessary to prevent 'unbound variable' and 'unbound function' errors with symbols and lists.

Examples:

1. The cl:multiple-value-bind macro binds values returned by the cl:values function:

(defun multiple-value-function ()
  (cl:values 1 2 3))  ; multiple return values

> (cl:multiple-value-bind (a b c)
      (multiple-value-function)
    (list a b c))
(1 2 3)

2. If there are no values returned in the Nyquist *rslt* variable, the normal function return value is bound to the first symbol and all remaining symbols are bound to NIL:

(defun normal-lisp-function ()
  (+ 1 1))  ; normal return value

> (cl:multiple-value-bind (a b c)
      (normal-lisp-function)
    (list a b c))
(2 NIL NIL)

3. If there are less values than symbols, the extra symbols are bound to NIL:

(defun not-enough-values-function ()
  (cl:values 1 2))  ; multiple return values

> (cl:multiple-value-bind (a b c)
      (not-enough-values-function)
    (list a b c))
(1 2 NIL)

4. If there are more values than symbols, the extra values are ignored:

(defun too-many-values-function ()
  (cl:values 1 2 3 4 5))  ; multiple return values

> (cl:multiple-value-bind (a b c)
      (too-many-values-function)
    (list a b c))
(1 2 3)

  Back to top


Nyquist / XLISP 2.0  -  Contents | Tutorials | Examples | Reference