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

cl:multiple-value-setq


The cl:multiple-value-setq macro assigns multiple values to multiple variables:

(cl:multiple-value-setq symbols expr)
symbols - a list of symbols
expr - a Lisp expression returning one or more values
returns - the primary value returned by evaluating the expression

(defmacro cl:multiple-value-setq (symbols expr)
  (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))
         (assignments (list 'setq)))
    (dotimes (index number-of-symbols)
      (push (nth index symbols) assignments)
      (push (when (< index number-of-values)
              (list 'quote (nth index values)))
            assignments))
    (setq assignments (reverse assignments))
    `(progn ,assignments ',result)))

The expression is evaluated, and each symbol is assigned to the corresponding value returned by the evaluation. If there are more symbols than values returned, NIL is assigned to the extra symbols. If there are more values than symbols, the extra values are discarded.

The cl:*multiple-values* variable is  T  if evaluating the expression returns multiple values and NIL with a normal return value.

The cl:multiple-value-setq macro assigns multiple values to multiple variables using setq:

> (macroexpand-1 '(cl:multiple-value-setq (a b c)
                    (cl:values 1 2 3)))
(PROGN (SETQ A (QUOTE 1)
             B (QUOTE 2)
             C (QUOTE 3))
       (QUOTE 1))

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

Examples:

1. The cl:multiple-value-setq macro assigns values returned by the cl:values function:

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

> (let ((a 'A) (b 'B) (c 'C))
    (cl:multiple-value-setq (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 assigned to the first symbol and all remaining symbols are assigned to NIL:

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

> (let ((a 'A) (b 'B) (c 'C))
    (cl:multiple-value-setq (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 assigned to NIL:

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

> (let ((a 'A) (b 'B) (c 'C))
    (cl:multiple-value-setq (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

> (let ((a 'A) (b 'B) (c 'C))
    (cl:multiple-value-setq (a b c)
      (too-many-values-function))
    (list a b c))
(1 2 3)

5. Symbols not contained in the cl:multiple-value-setq symbol-list are not changed:

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

> (let ((a 'A) (b 'B) (c 'C) (d 'D) (e 'E))
    (cl:multiple-value-setq (a b c)
      (multiple-value-function))
    (list a b c d e))
(1 2 3 D E)

5. If no bindings exist, new variables will be created:

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

> (let ((c 'C) (d 'D) (e 'E))
    (cl:multiple-value-setq (a b c)
      (multiple-value-function))
    (list a b c d e))
(1 2 3 D E)

Caution: In the last example, two global variables 'a' and 'b' were created, while the lexical let variable 'c' was assigned to the value 3:

> (list a b)
(1 2)

> (list a b c)
error: unbound variable - C

The lexical let binding of 'c' does not exist in the global top-level. See Environment for more details about variables.

  Back to top


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