cl: Modify Macros

 
 4.2.2 Modify Macros
 -------------------
 
 This package defines a number of macros that operate on generalized
 variables.  Many are interesting and useful even when the PLACE is just
 a variable name.
 
  -- Macro: cl-psetf [place form]...
      This macro is to ‘setf’ what ‘cl-psetq’ is to ‘setq’: When several
      PLACEs and FORMs are involved, the assignments take place in
      parallel rather than sequentially.  Specifically, all subforms are
      evaluated from left to right, then all the assignments are done (in
      an undefined order).
 
  -- Macro: cl-incf place &optional x
      This macro increments the number stored in PLACE by one, or by X if
      specified.  The incremented value is returned.  For example,
      ‘(cl-incf i)’ is equivalent to ‘(setq i (1+ i))’, and ‘(cl-incf
      (car x) 2)’ is equivalent to ‘(setcar x (+ (car x) 2))’.
 
      As with ‘setf’, care is taken to preserve the “apparent” order of
      evaluation.  For example,
 
           (cl-incf (aref vec (cl-incf i)))
 
      appears to increment ‘i’ once, then increment the element of ‘vec’
      addressed by ‘i’; this is indeed exactly what it does, which means
      the above form is _not_ equivalent to the “obvious” expansion,
 
           (setf (aref vec (cl-incf i))
                 (1+ (aref vec (cl-incf i))))   ; wrong!
 
      but rather to something more like
 
           (let ((temp (cl-incf i)))
             (setf (aref vec temp) (1+ (aref vec temp))))
 
      Again, all of this is taken care of automatically by ‘cl-incf’ and
      the other generalized-variable macros.
 
      As a more Emacs-specific example of ‘cl-incf’, the expression
      ‘(cl-incf (point) N)’ is essentially equivalent to ‘(forward-char
      N)’.
 
  -- Macro: cl-decf place &optional x
      This macro decrements the number stored in PLACE by one, or by X if
      specified.
 
  -- Macro: cl-pushnew x place &key :test :test-not :key
      This macro inserts X at the front of the list stored in PLACE, but
      only if X was not ‘eql’ to any existing element of the list.  The
      optional keyword arguments are interpreted in the same way as for
      ‘cl-adjoin’.  SeeLists as Sets.
 
  -- Macro: cl-shiftf place... newvalue
      This macro shifts the PLACEs left by one, shifting in the value of
      NEWVALUE (which may be any Lisp expression, not just a generalized
      variable), and returning the value shifted out of the first PLACE.
      Thus, ‘(cl-shiftf A B C D)’ is equivalent to
 
           (prog1
               A
             (cl-psetf A B
                       B C
                       C D))
 
      except that the subforms of A, B, and C are actually evaluated only
      once each and in the apparent order.
 
  -- Macro: cl-rotatef place...
      This macro rotates the PLACEs left by one in circular fashion.
      Thus, ‘(cl-rotatef A B C D)’ is equivalent to
 
           (cl-psetf A B
                     B C
                     C D
                     D A)
 
      except for the evaluation of subforms.  ‘cl-rotatef’ always returns
      ‘nil’.  Note that ‘(cl-rotatef A B)’ conveniently exchanges A and
      B.
 
    The following macros were invented for this package; they have no
 analogues in Common Lisp.
 
  -- Macro: cl-letf (bindings...) forms...
      This macro is analogous to ‘let’, but for generalized variables
      rather than just symbols.  Each BINDING should be of the form
      ‘(PLACE VALUE)’; the original contents of the PLACEs are saved, the
      VALUEs are stored in them, and then the body FORMs are executed.
      Afterwards, the PLACES are set back to their original saved
      contents.  This cleanup happens even if the FORMs exit irregularly
      due to a ‘throw’ or an error.
 
      For example,
 
           (cl-letf (((point) (point-min))
                     (a 17))
                ...)
 
      moves point in the current buffer to the beginning of the buffer,
      and also binds ‘a’ to 17 (as if by a normal ‘let’, since ‘a’ is
      just a regular variable).  After the body exits, ‘a’ is set back to
      its original value and point is moved back to its original
      position.
 
      Note that ‘cl-letf’ on ‘(point)’ is not quite like a
      ‘save-excursion’, as the latter effectively saves a marker which
      tracks insertions and deletions in the buffer.  Actually, a
      ‘cl-letf’ of ‘(point-marker)’ is much closer to this behavior.
      (‘point’ and ‘point-marker’ are equivalent as ‘setf’ places; each
      will accept either an integer or a marker as the stored value.)
 
      Like in the case of ‘let’, the VALUE forms are evaluated in the
      order they appear, but the order of bindings is unspecified.
      Therefore, avoid binding the same PLACE more than once in a single
      ‘cl-letf’ form.
 
      Since generalized variables look like lists, ‘let’’s shorthand of
      using ‘foo’ for ‘(foo nil)’ as a BINDING would be ambiguous in
      ‘cl-letf’ and is not allowed.
 
      However, a BINDING specifier may be a one-element list ‘(PLACE)’,
      which is similar to ‘(PLACE PLACE)’.  In other words, the PLACE is
      not disturbed on entry to the body, and the only effect of the
      ‘cl-letf’ is to restore the original value of PLACE afterwards.
 
      Note that in this case, and in fact almost every case, PLACE must
      have a well-defined value outside the ‘cl-letf’ body.  There is
      essentially only one exception to this, which is PLACE a plain
      variable with a specified VALUE (such as ‘(a 17)’ in the above
      example).
 
  -- Macro: cl-letf* (bindings...) forms...
      This macro is to ‘cl-letf’ what ‘let*’ is to ‘let’: It does the
      bindings in sequential rather than parallel order.
 
  -- Macro: cl-callf FUNCTION PLACE ARGS...
      This is the “generic” modify macro.  It calls FUNCTION, which
      should be an unquoted function name, macro name, or lambda.  It
      passes PLACE and ARGS as arguments, and assigns the result back to
      PLACE.  For example, ‘(cl-incf PLACE N)’ is the same as ‘(cl-callf
      + PLACE N)’.  Some more examples:
 
           (cl-callf abs my-number)
           (cl-callf concat (buffer-name) "<" (number-to-string n) ">")
           (cl-callf cl-union happy-people (list joe bob) :test 'same-person)
 
      Note again that ‘cl-callf’ is an extension to standard Common Lisp.
 
  -- Macro: cl-callf2 FUNCTION ARG1 PLACE ARGS...
      This macro is like ‘cl-callf’, except that PLACE is the _second_
      argument of FUNCTION rather than the first.  For example, ‘(push X
      PLACE)’ is equivalent to ‘(cl-callf2 cons X PLACE)’.
 
    The ‘cl-callf’ and ‘cl-callf2’ macros serve as building blocks for
 other macros like ‘cl-incf’, and ‘cl-pushnew’.  The ‘cl-letf’ and
 ‘cl-letf*’ macros are used in the processing of symbol macros; See
 Macro Bindings.