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を評価する。