elisp: Building Lists

 
 5.4 Building Cons Cells and Lists
 =================================
 
 Many functions build lists, as lists reside at the very heart of Lisp.
 ‘cons’ is the fundamental list-building function; however, it is
 interesting to note that ‘list’ is used more times in the source code
 for Emacs than ‘cons’.
 
  -- Function: cons object1 object2
      This function is the most basic function for building new list
      structure.  It creates a new cons cell, making OBJECT1 the CAR, and
      OBJECT2 the CDR.  It then returns the new cons cell.  The arguments
      OBJECT1 and OBJECT2 may be any Lisp objects, but most often OBJECT2
      is a list.
 
           (cons 1 '(2))
                ⇒ (1 2)
           (cons 1 '())
                ⇒ (1)
           (cons 1 2)
                ⇒ (1 . 2)
 
      ‘cons’ is often used to add a single element to the front of a
      list.  This is called “consing the element onto the list”.  (1) For
      example:
 
           (setq list (cons newelt list))
 
      Note that there is no conflict between the variable named ‘list’
      used in this example and the function named ‘list’ described below;
      any symbol can serve both purposes.
 
  -- Function: list &rest objects
      This function creates a list with OBJECTS as its elements.  The
      resulting list is always ‘nil’-terminated.  If no OBJECTS are
      given, the empty list is returned.
 
           (list 1 2 3 4 5)
                ⇒ (1 2 3 4 5)
           (list 1 2 '(3 4 5) 'foo)
                ⇒ (1 2 (3 4 5) foo)
           (list)
                ⇒ nil
 
  -- Function: make-list length object
      This function creates a list of LENGTH elements, in which each
      element is OBJECT.  Compare ‘make-list’ with ‘make-string’ (See
      Creating Strings).
 
           (make-list 3 'pigs)
                ⇒ (pigs pigs pigs)
           (make-list 0 'pigs)
                ⇒ nil
           (setq l (make-list 3 '(a b)))
                ⇒ ((a b) (a b) (a b))
           (eq (car l) (cadr l))
                ⇒ t
 
  -- Function: append &rest sequences
      This function returns a list containing all the elements of
      SEQUENCES.  The SEQUENCES may be lists, vectors, bool-vectors, or
      strings, but the last one should usually be a list.  All arguments
      except the last one are copied, so none of the arguments is
      altered.  (See ‘nconc’ in SeeRearrangement, for a way to join
      lists with no copying.)
 
      More generally, the final argument to ‘append’ may be any Lisp
      object.  The final argument is not copied or converted; it becomes
      the CDR of the last cons cell in the new list.  If the final
      argument is itself a list, then its elements become in effect
      elements of the result list.  If the final element is not a list,
      the result is a dotted list since its final CDR is not ‘nil’ as
      required in a true list.
 
    Here is an example of using ‘append’:
 
      (setq trees '(pine oak))
           ⇒ (pine oak)
      (setq more-trees (append '(maple birch) trees))
           ⇒ (maple birch pine oak)
 
      trees
           ⇒ (pine oak)
      more-trees
           ⇒ (maple birch pine oak)
      (eq trees (cdr (cdr more-trees)))
           ⇒ t
 
    You can see how ‘append’ works by looking at a box diagram.  The
 variable ‘trees’ is set to the list ‘(pine oak)’ and then the variable
 ‘more-trees’ is set to the list ‘(maple birch pine oak)’.  However, the
 variable ‘trees’ continues to refer to the original list:
 
      more-trees                trees
      |                           |
      |     --- ---      --- ---   -> --- ---      --- ---
       --> |   |   |--> |   |   |--> |   |   |--> |   |   |--> nil
            --- ---      --- ---      --- ---      --- ---
             |            |            |            |
             |            |            |            |
              --> maple    -->birch     --> pine     --> oak
 
    An empty sequence contributes nothing to the value returned by
 ‘append’.  As a consequence of this, a final ‘nil’ argument forces a
 copy of the previous argument:
 
      trees
           ⇒ (pine oak)
      (setq wood (append trees nil))
           ⇒ (pine oak)
      wood
           ⇒ (pine oak)
      (eq wood trees)
           ⇒ nil
 
 This once was the usual way to copy a list, before the function
 ‘copy-sequence’ was invented.  SeeSequences Arrays Vectors.
 
    Here we show the use of vectors and strings as arguments to ‘append’:
 
      (append [a b] "cd" nil)
           ⇒ (a b 99 100)
 
    With the help of ‘apply’ (SeeCalling Functions), we can append
 all the lists in a list of lists:
 
      (apply 'append '((a b c) nil (x y z) nil))
           ⇒ (a b c x y z)
 
    If no SEQUENCES are given, ‘nil’ is returned:
 
      (append)
           ⇒ nil
 
    Here are some examples where the final argument is not a list:
 
      (append '(x y) 'z)
           ⇒ (x y . z)
      (append '(x y) [z])
           ⇒ (x y . [z])
 
 The second example shows that when the final argument is a sequence but
 not a list, the sequence’s elements do not become elements of the
 resulting list.  Instead, the sequence becomes the final CDR, like any
 other non-list final argument.
 
  -- Function: copy-tree tree &optional vecp
      This function returns a copy of the tree ‘tree’.  If TREE is a cons
      cell, this makes a new cons cell with the same CAR and CDR, then
      recursively copies the CAR and CDR in the same way.
 
      Normally, when TREE is anything other than a cons cell, ‘copy-tree’
      simply returns TREE.  However, if VECP is non-‘nil’, it copies
      vectors too (and operates recursively on their elements).
 
  -- Function: number-sequence from &optional to separation
      This returns a list of numbers starting with FROM and incrementing
      by SEPARATION, and ending at or just before TO.  SEPARATION can be
      positive or negative and defaults to 1.  If TO is ‘nil’ or
      numerically equal to FROM, the value is the one-element list
      ‘(FROM)’.  If TO is less than FROM with a positive SEPARATION, or
      greater than FROM with a negative SEPARATION, the value is ‘nil’
      because those arguments specify an empty sequence.
 
      If SEPARATION is 0 and TO is neither ‘nil’ nor numerically equal to
      FROM, ‘number-sequence’ signals an error, since those arguments
      specify an infinite sequence.
 
      All arguments are numbers.  Floating-point arguments can be tricky,
      because floating-point arithmetic is inexact.  For instance,
      depending on the machine, it may quite well happen that
      ‘(number-sequence 0.4 0.6 0.2)’ returns the one element list
      ‘(0.4)’, whereas ‘(number-sequence 0.4 0.8 0.2)’ returns a list
      with three elements.  The Nth element of the list is computed by
      the exact formula ‘(+ FROM (* N SEPARATION))’.  Thus, if one wants
      to make sure that TO is included in the list, one can pass an
      expression of this exact type for TO.  Alternatively, one can
      replace TO with a slightly larger value (or a slightly more
      negative value if SEPARATION is negative).
 
      Some examples:
 
           (number-sequence 4 9)
                ⇒ (4 5 6 7 8 9)
           (number-sequence 9 4 -1)
                ⇒ (9 8 7 6 5 4)
           (number-sequence 9 4 -2)
                ⇒ (9 7 5)
           (number-sequence 8)
                ⇒ (8)
           (number-sequence 8 5)
                ⇒ nil
           (number-sequence 5 8 -1)
                ⇒ nil
           (number-sequence 1.5 6 2)
                ⇒ (1.5 3.5 5.5)
 
    ---------- Footnotes ----------
 
    (1) There is no strictly equivalent way to add an element to the end
 of a list.  You can use ‘(append LISTNAME (list NEWELT))’, which creates
 a whole new list by copying LISTNAME and adding NEWELT to its end.  Or
 you can use ‘(nconc LISTNAME (list NEWELT))’, which modifies LISTNAME by
 following all the CDRs and then replacing the terminating ‘nil’.
 Compare this to adding an element to the beginning of a list with
 ‘cons’, which neither copies nor modifies the list.