Next: , Up: Basic Concepts   [Contents][Index]


2.1 For Clauses

The expansion of an iteration form is driven by a series of for clauses, classified into iteration clauses and special clauses. Iteration clauses decide the shapes of the expanded forms, and special clauses wrap the partially expanded forms in some ways. For example, an iteration clause (item '(a 2 "3")) decides that item is bound to each car of the literal list (see (elisp)Quoting) sequence (a 2 "3") and that the iteration is stopped when it reaches the terminating empty list (see (elisp)Box Diagrams)6. A special clause (:if (numberp item)) following the iteration clause decides that the partially expanded form is skipped unless item is numberp (see (elisp)Predicates on Numbers).

sum is only updated when item is numberp:

(for-fold ((sum 0))
    ((item '(a 2 "3"))
     (:if (numberp item))
     (+ item sum)))
     ⇒ 2

An equivalent named-let form:

(let ((sum 0))
  (named-let loop ((sum sum)
                   (tail '(a 2 "3")))
    (if (null tail)
        sum
      (let ((item (car tail)))
        (loop (if (numberp item)
                  (+ item sum)
                sum)
              (cdr tail))))))
     ⇒ 2

Adjacent iteration clauses are considered parallel and thus iterated at the same time. When one of them ends, the iteration ends. This gives rise to the usefulness of infinite sequences.

(for-in-infinite-range [start [step]])7 is an infinite sequence:

(for-list ((natural (for-in-infinite-range 0))
           (item '(a b c))
           (cons natural item)))
     ⇒ ((0 . a) (1 . b) (2 . c))

As a consequence, special clauses also serve the purpose of delimiting iteration clauses into groups. A group of iteration clauses preceded by another group is effectively nested. Because the nesting behavior is so commonly desired, implicitly nesting variants of the iteration forms are provided. They transform the for clauses by separating each pair of adjacent iteration clauses with a vacuous special clause.

(item2 '(2 3 4)) nested by (item1 '(1 2)) due to the presence of (:do):

(for-list ((item1 '(1 2))
           (:do)
           (item2 '(2 3 4))
           (cons item1 item2)))
     ⇒ ((1 . 2) (1 . 3) (1 . 4) (2 . 2) (2 . 3) (2 . 4))

An equivalent for-list* form:

(for-list* ((item1 '(1 2))
            (item2 '(2 3 4))
            (cons item1 item2)))
     ⇒ ((1 . 2) (1 . 3) (1 . 4) (2 . 2) (2 . 3) (2 . 4))

An iteration clause normally has the form (pattern sequence) where pattern is a pcase pattern and sequence is a sequence form. Alternatively, it can have the form (sequence), in which case it is transformed to (identifier sequence) with a generated identifier8 (see (elisp)Creating Symbols) as identifier. A special clause has the form (keyword . subforms) where keyword is one of the keywords (see (elisp)Constant Variables) accepted by the grammar and the form of subforms is decided by keyword.


Footnotes

(5)

Following R5RS (Revised5 Report on the Algorithmic Language Scheme), an error does not specify whether or when the error is detected or reported.

(6)

In this manual, unless otherwise specified, an object is a list if and only if it is a proper list. Following Common Lisp and Emacs Lisp (see (elisp)Cons Cells), a proper list is either the empty list or a list terminated by the empty list. It is an error5 for it to be any other structure produced by cons (see (elisp)Building Lists), that is, a circular list or a dotted list.

(7)

In this manual, a metavariable is typeset as ‘metavariable’, an optional form as ‘[optional-form]’, and a form repeated once or more as ‘repeated-form’. This is the same as the Emacs Lisp Manual (see (elisp)A Sample Function Description) modulo the ‘repeated-form’ convention.

(8)

In R6RS (Revised6 Report on the Algorithmic Language Scheme), an identifier is roughly a syntax object of non-constant symbol. Emacs Lisp does not have the concept of syntax object. Nonetheless, this manual follows such usage of the terminology.


Next: Sequence Forms, Up: Basic Concepts   [Contents][Index]