GNU Info

Info Node: (cl)Modify Macros

(cl)Modify Macros


Next: Customizing Setf Prev: Basic Setf Up: Generalized Variables
Enter node , (file) or (file)node

Modify Macros
-------------

This package defines a number of other macros besides `setf' that
operate on generalized variables.  Many are interesting and useful even
when the PLACE is just a variable name.

 - Special Form: psetf [place form]...
     This macro is to `setf' what `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).

 - Special Form: 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,
     `(incf i)' is equivalent to `(setq i (1+ i))', and `(incf (car x)
     2)' is equivalent to `(setcar x (+ (car x) 2))'.

     Once again, care is taken to preserve the "apparent" order of
     evaluation.  For example,

          (incf (aref vec (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 (incf i)) (1+ (aref vec (incf i))))   ; Wrong!

     but rather to something more like

          (let ((temp (incf i)))
            (setf (aref vec temp) (1+ (aref vec temp))))

     Again, all of this is taken care of automatically by `incf' and
     the other generalized-variable macros.

     As a more Emacs-specific example of `incf', the expression `(incf
     (point) N)' is essentially equivalent to `(forward-char N)'.

 - Special Form: decf place &optional x
     This macro decrements the number stored in PLACE by one, or by X
     if specified.

 - Special Form: pop place
     This macro removes and returns the first element of the list stored
     in PLACE.  It is analogous to `(prog1 (car PLACE) (setf PLACE (cdr
     PLACE)))', except that it takes care to evaluate all subforms only
     once.

 - Special Form: push x place
     This macro inserts X at the front of the list stored in PLACE.  It
     is analogous to `(setf PLACE (cons X PLACE))', except for
     evaluation of the subforms.

 - Special Form: 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
     `adjoin'.  Note: Lists as Sets.

 - Special Form: 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, `(shiftf A B C D)' is equivalent to

          (prog1
              A
            (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.

 - Special Form: rotatef place...
     This macro rotates the PLACEs left by one in circular fashion.
     Thus, `(rotatef A B C D)' is equivalent to

          (psetf A B
                 B C
                 C D
                 D A)

     except for the evaluation of subforms.  `rotatef' always returns
     `nil'.  Note that `(rotatef A B)' conveniently exchanges A and B.

   The following macros were invented for this package; they have no
analogues in Common Lisp.

 - Special Form: 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,

          (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 `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 `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.)

     Since generalized variables look like lists, `let''s shorthand of
     using `foo' for `(foo nil)' as a BINDING would be ambiguous in
     `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
     `letf' is to restore the original value of PLACE afterwards.  (The
     redundant access-and-store suggested by the `(PLACE PLACE)'
     example does not actually occur.)

     In most cases, the PLACE must have a well-defined value on entry
     to the `letf' form.  The only exceptions are plain variables and
     calls to `symbol-value' and `symbol-function'.  If the symbol is
     not bound on entry, it is simply made unbound by `makunbound' or
     `fmakunbound' on exit.

 - Special Form: letf* (bindings...) forms...
     This macro is to `letf' what `let*' is to `let': It does the
     bindings in sequential rather than parallel order.

 - Special Form: 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, `(incf PLACE N)' is the same as `(callf +
     PLACE N)'.  Some more examples:

          (callf abs my-number)
          (callf concat (buffer-name) "<" (int-to-string n) ">")
          (callf union happy-people (list joe bob) :test 'same-person)

     Note: Customizing Setf, for `define-modify-macro', a way to
     create even more concise notations for modify macros.  Note again
     that `callf' is an extension to standard Common Lisp.

 - Special Form: callf2 FUNCTION ARG1 PLACE ARGS...
     This macro is like `callf', except that PLACE is the _second_
     argument of FUNCTION rather than the first.  For example, `(push X
     PLACE)' is equivalent to `(callf2 cons X PLACE)'.

   The `callf' and `callf2' macros serve as building blocks for other
macros like `incf', `pushnew', and `define-modify-macro'.  The `letf'
and `letf*' macros are used in the processing of symbol macros; Note:
Macro Bindings.


automatically generated by info2www version 1.2.2.9