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]