setfマクロは汎変数に作用する最も基本的な方法である。
このマクロはformを評価し、それをplaceに格納する。
placeは有効な汎変数フォームでなければならない。いくつかの
placeとformの対がある場合、代入はちょうどsetq
のように順に行なわれる。setfは最後のformの値を戻す。
下記のLispフォームは汎変数として働くので、setfのplace引数
に正しく現れてもよい:
(setf x y)は
(setq x y)と正確に同等であり、setq自身はsetfが
存在する現在では厳密には冗長である。しかし、多くのプログラマは純粋に
スタイルまたは歴史的な理由で、単純変数の設定のためにはsetqを
好み続けている。マクロ(setf x y)は実際には(setq x y)へ
展開するので、コンパイルされたコードで使う場合に性能上の不利益はない。
car cdr caar .. cddddr nth rest first .. tenth aref elt nthcdr symbol-function symbol-value symbol-plist get get* getf gethash subseq
nthcdrとgetfのためには、関数のリスト引数はそれ自身有効な
placeフォームでなければならないことに注意せよ。たとえば、
(setf (nthcdr 0 foo) 7)はfoo自身に7を設定する。
nthcdrを場所とするpushやpopはリストのどの位置にも
挿入や削除するために使うことができることに注意せよ。place
フォームとしてnthcdrを使うことは標準Common Lispへの拡張である。
setf可能である(これらのいくつかはEmacs 19
またはLucid Emacsだけで定義されている)。
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-cut-buffer keymap-parent x-get-cutbuffer local-key-binding x-get-secondary-selection mark x-get-selection mark-marker
これらの多くは、current-local-map用のuse-local-mapや
point用のgoto-charのように、ダイレクトに対応する“設定”
関数を持つ。point-minのようないくつかは、setf
されるとより長いコード列(この場合は
(narrow-to-region x (point-max)))に展開する。
(substring subplace n [m])の呼び出し
は、subplace自身が現在の値が文字列である正しい汎変数であり、格納
される値も文字列である。新たな文字列は宛先文字列の指定された
部分につながれる。たとえば:
(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")
上のリストの汎変数buffer-substringも、現バッファの一部を
置き換えることでこのように動作する。
(apply 'func …)または
(apply (function func) …)の呼び出し; 標準Emacsの
place 関数はどれもこの意味で適切ではないので、この機能は
define-setf-methodかdefsetfの長いフォームで自身が
定義するplaceで使われる場合のみ興味あるものである。
setfが結果として
生じるフォームに適用される場合。
defsetfまたはdefine-setf-methodがそのために
作られたすべてのフォーム。
setfへのplace引数にこれら以外のあらゆるフォームを使うと
エラーを通知する。
setfマクロは適正な左から右への順序ですべての部分フォームを
評価するように注意する; たとえば、
(setf (aref vec (incf i)) i)
は(incf i)を正確に一度、続くiへのアクセスの前に
評価するように見える; setfエクスパンダはaref
のためにどんなsetfメソッドが定義されても実際にこのように動作することを
確実にするために、必要な一時的変数を挿入する(この場合asetが
使われるだろうが、asetは便利な順序でその
引数をとるのでそのような手段は必要ないだろう)。
しかし、placeフォームが通常ではない順序でその引数を明示的に 評価するマクロの場合、この通常ではない順序は保存される。Steeleからの 例を改作して、以下があるとすれば
(defmacro wrong-order (x y) (list 'aref y x))
フォーム(setf (wrong-order a b) 17)は、ちょうど
wrong-orderへの実際の呼び出しのように、bを最初に
評価しそれからaを評価する。