Next: Modify Macros, Previous: Generalized Variables, Up: Generalized Variables

#### 5.2.1 Basic Setf

The `setf` macro is the most basic way to operate on generalized variables.

— Special Form: setf [place form]...

> This macro evaluates form and stores it in place, which must be a valid generalized variable form. If there are several place and form pairs, the assignments are done sequentially just as with `setq`. `setf` returns the value of the last form.

> The following Lisp forms will work as generalized variables, and so may appear in the place argument of `setf`:

> - A symbol naming a variable. In other words, `(setf x y)` is exactly equivalent to `(setq x y)`, and `setq` itself is strictly speaking redundant now that `setf` exists. Many programmers continue to prefer `setq` for setting simple variables, though, purely for stylistic or historical reasons. The macro `(setf x y)` actually expands to `(setq x y)`, so there is no performance penalty for using it in compiled code.
> - A call to any of the following Lisp functions:

>                      car                 cdr                 caar .. cddddr
>                      nth                 rest                first .. tenth
>                      aref                elt                 nthcdr
>                      symbol-function     symbol-value        symbol-plist
>                      get                 get*                getf
>                      gethash             subseq

>   Note that for `nthcdr` and `getf`, the list argument of the function must itself be a valid place form. For example, `(setf (nthcdr 0 foo) 7)` will set `foo` itself to 7. Note that `push` and `pop` on an `nthcdr` place can be used to insert or delete at any position in a list. The use of `nthcdr` as a place form is an extension to standard Common Lisp.

> - The following Emacs-specific functions are also `setf`-able.

>                      buffer-file-name                  marker-position
>                      buffer-modified-p                 match-data
>                      buffer-name                       mouse-position
>                      buffer-string                     overlay-end
>                      buffer-substring                  overlay-get
>                      current-buffer                    overlay-start
>                      current-case-table                point
>                      current-column                    point-marker
>                      current-global-map                point-max
>                      current-input-mode                point-min
>                      current-local-map                 process-buffer
>                      current-window-configuration      process-filter
>                      default-file-modes                process-sentinel
>                      default-value                     read-mouse-position
>                      documentation-property            screen-height
>                      extent-data                       screen-menubar
>                      extent-end-position               screen-width
>                      extent-start-position             selected-window
>                      face-background                   selected-screen
>                      face-background-pixmap            selected-frame
>                      face-font                         standard-case-table
>                      face-foreground                   syntax-table
>                      face-underline-p                  window-buffer
>                      file-modes                        window-dedicated-p
>                      frame-height                      window-display-table
>                      frame-parameters                  window-height
>                      frame-visible-p                   window-hscroll
>                      frame-width                       window-point
>                      get-register                      window-start
>                      getenv                            window-width
>                      global-key-binding                x-get-secondary-selection
>                      keymap-parent                     x-get-selection
>                      local-key-binding
>                      mark
>                      mark-marker

>   Most of these have directly corresponding “set” functions, like `use-local-map` for `current-local-map`, or `goto-char` for `point`. A few, like `point-min`, expand to longer sequences of code when they are `setf`'d (`(narrow-to-region x (point-max))` in this case).

> - A call of the form `(substring` subplace n `[`m`])`, where subplace is itself a valid generalized variable whose current value is a string, and where the value stored is also a string. The new string is spliced into the specified part of the destination string. For example:

>                      (setq a (list "hello" "world"))
>                           ⇒ ("hello" "world")
>                      (cadr a)
>                           ⇒ "world"
>                      (substring (cadr a) 2 4)
>                           ⇒ "rl"
>                      (setf (substring (cadr a) 2 4) "o")
>                           ⇒ "o"
>                      (cadr a)
>                           ⇒ "wood"
>                      a
>                           ⇒ ("hello" "wood")

>   The generalized variable `buffer-substring`, listed above, also works in this way by replacing a portion of the current buffer.

> - A call of the form `(apply '`func `...)` or `(apply (function` func`) ...)`, where func is a `setf`-able function whose store function is “suitable” in the sense described in Steele's book; since none of the standard Emacs place functions are suitable in this sense, this feature is only interesting when used with places you define yourself with `define-setf-method` or the long form of `defsetf`.
> - A macro call, in which case the macro is expanded and `setf` is applied to the resulting form.
> - Any form for which a `defsetf` or `define-setf-method` has been made.

> Using any forms other than these in the place argument to `setf` will signal an error.

> The `setf` macro takes care to evaluate all subforms in the proper left-to-right order; for example,

>               (setf (aref vec (incf i)) i)

> looks like it will evaluate `(incf i)` exactly once, before the following access to `i`; the `setf` expander will insert temporary variables as necessary to ensure that it does in fact work this way no matter what setf-method is defined for `aref`. (In this case, `aset` would be used and no such steps would be necessary since `aset` takes its arguments in a convenient order.)

> However, if the place form is a macro which explicitly evaluates its arguments in an unusual order, this unusual order will be preserved. Adapting an example from Steele, given

>               (defmacro wrong-order (x y) (list 'aref y x))

> the form `(setf (wrong-order` a b`) 17)` will evaluate b first, then a, just as in an actual call to `wrong-order`.