setfマクロ ¶setfマクロはジェネリック変数を操作するもっとも基本的な方法です。setfフォームはsetqと似ていますが、シンボルだけでなくそれぞれのペアーの1つ目(左)の任意のplace
formを受け入れます。たとえば(setf (car a)
b)はaのcarをbにセットして(setcar a
b)と同じ操作を行いますが、このタイプのplaceにセットやアクセスするために2つの関数を個別に覚える必要はありません。
このマクロはformを評価して、その値をplaceに格納する。placeは有効なジェネリック変数フォームでなければならない。複数のplace/formペアーがある場合の割り当てについてはsetqの場合と同様。setfは最後のformの値をリターンする。
以下のLispフォームはEmacsではジェネリック変数として機能するフォームなので、setfのplace引数にすることができます:
(setf x y)は完全に(setq x
y)と正に等しく、厳密に言うとsetq自体はsetfが存在するので冗長です。これは純粋にスタイルと歴史的な理由によりますが、ほとんどのプログラマーは依然として単純な変数へのセットにはsetqの方を好みます。マクロ(setf
x y)は実際には(setq x y)に展開されるので、コンパイルされたコードでこれを使用することにパフォーマンス的な不利はありません。
aref cddr symbol-function car elt symbol-plist caar get symbol-value cadr gethash cdr nth cdar nthcdr
alist-get overlay-start default-value overlay-get face-background process-buffer face-font process-filter face-foreground process-get face-stipple process-sentinel face-underline-p terminal-parameter file-modes window-buffer frame-parameter window-dedicated-p frame-parameters window-display-table get-register window-hscroll getenv window-parameter keymap-parent window-point match-data window-start overlay-end
(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")
ifやcondというコンディションも機能する。たとえば以下はfooかbarいずれかの変数をzotにセットする例:
(setf (if (zerop (random 2))
foo
bar)
'zot)
どのように処理すれば良いか未知なplaceフォームを渡すと、setfはエラーをシグナルします。
nthcdrの場合、関数のリスト引数はそれ自体が有効なplaceフォームでなければならないことに注意してください。たとえば(setf
(nthcdr 0 foo) 7)は、foo自体に7をセットするでしょう。
マクロpush(リスト変数の変更を参照)とpop(リスト要素へのアクセスを参照)は、リストだけでなくジェネリック変数を操作できます。(pop
place)はplace内に格納されたリストの最初の要素を削除してリターンします。これは(prog1 (car
place) (setf place (cdr
place)))と似ていますが、すべてのサブフォームを一度だけ評価します。(push x
place)はplace内に格納されたリストの一番前にxを挿入します。これは(setf
place (cons x
place))と似ていますが、サブフォームの評価が異なります。nthcdr
placeへのpushとpopは、リスト内の任意の位置での挿入や削除に使用できることに注意してください。
cl-libライブラリーでは追加のsetf
placeを含む、ジェネリック変数にたいするさまざまな拡張が定義されています。Generalized Variables in Common Lisp Extensionsを参照してください。