Previous: Sequence Forms, Up: Basic Concepts [Contents][Index]
It is not uncommon for one to iteratively update multiple state variables. To functionally do so, it is convenient to be able to produce multiple values from a single expression where the values are in turn consumed by the self-tail-recursive function. Unfortunately, Emacs Lisp does not support multiple values. To circumvent the limitation, a partial support for multiple-value forms is implemented10.
A cl-loop
form involving multiple state variables:
(cl-loop with value1 = 0 and value2 = '() and value3 = -1.0e+INF for number below 5 do (cl-incf value1 number) (push number value2) (cl-callf max value3 number) finally return (list value1 (nreverse value2) value3)) ⇒ (10 (0 1 2 3 4) 4)
An equivalent for-do
form:
(let ((value1 0) (value2 '()) (value3 -1.0e+INF)) (for-do ((number 5) (:do (cl-incf value1 number) (push number value2) (cl-callf max value3 number)))) (list value1 (nreverse value2) value3)) ⇒ (10 (0 1 2 3 4) 4)
An equivalent for-fold
form:
(for-fold ((value1 0) (value2 '()) (value3 -1.0e+INF) (:result (list value1 (nreverse value2) value3))) ((number 5) (:values (+ number value1) (cons number value2) (max number value3)))) ⇒ (10 (0 1 2 3 4) 4)
Other than where the iteration forms expect a multiple-value form, multiple-value forms can appear in certain syntactic positions. It is an error for a multiple-value form to be in a syntactically invalid position. The formal grammar of multiple-value forms in an EBNF (Extended Backus–Naur Form) is as follows:
multiple-value-form = tail-form | (cond (guard . body)…) | (if guard multiple-value-form . body) | (let varlist . body) | (progn . body)
tail-form = expression | (:values [expression…])
body = ([expression…] multiple-value-form)
let = let | let*
progn = progn | save-current-buffer | save-excursion | save-restriction
Each multiple-value-form whose head is a global macro
(see (elisp)Defining Macros) or a local macro (see (cl)Macro
Bindings) is expanded (see (elisp)Expansion) ahead of time
and further inspected. The form of varlist is as in normal
let
and let*
forms. An expression and a guard
are both expressions where the value of latter is specifically
interpreted as a generalized Boolean11 value. A tail-form is a
tail form where an expression is equivalent to the form
(:values expression)
and a (:values
[expression…])
form produces as many values as
there are expressions. It is an error for two tail forms of a
multiple-value form to produce unmatched number of values. The grammar
is actually a subset of Emacs Lisp’s special forms (see (elisp)Special
Forms) with tail-form added. In a sense, special forms
are extended to support multiple-value forms where possible.
In a standard Scheme implementation, a continuation can receive multiple values, and correspondingly a procedure can deliver multiple values to its continuation. This is unfeasible to implement in Emacs Lisp. Instead, a multiple-value form is transformed to imperative updates with macro-expansion-time checking of the number of values.
Following
Common Lisp, a generalized Boolean value is an arbitrary Lisp
object where only nil
is false.
Previous: Sequence Forms, Up: Basic Concepts [Contents][Index]