このパッケージはsetfの他にも、汎変数に作用する多くのマクロを
定義する。placeが単に変数名である場合でも、多くは興味深く
有用である。
psetqがsetqに対応するように、このマクロはsetfに
対応する: いくつかのplaceとformを含むとき、代入は
順次にではなく並列に起こる。つまり、すべての部分フォームは左から右へ
評価され、それからすべての代入が(未定義の順序で)行なわれる。
このマクロはplaceに格納されている数を1だけ、または指定されている
場合はxだけ増やす。増やされた値が戻される。たとえば、
(incf i)は(setq i (1+ i))と同等であり、
(incf (car x) 2)は(setcar x (+ (car x) 2))と同等である。
もう一度、評価の“明白な”順序を保存するために注意が払われる。たとえば、
(incf (aref vec (incf i)))
はiを一度増やし、それからiでアドレスされるvecの
要素を増やすように現れる; これは実に正確にそれが行なうことであり、上の
フォームは“明らかな”展開と同等ではないことを意味し、
(setf (aref vec (incf i)) (1+ (aref vec (incf i)))) ; 間違い!
ではなく、むしろ何かより以下に似ているようなものである。
(let ((temp (incf i))) (setf (aref vec temp) (1+ (aref vec temp))))
もう一度、これらすべてはincfや他の汎変数マクロによって自動的に
注意が払われる。
incfのよりEmacs特有の例として、式(incf (point) n)
は(forward-char n)と本質的に同等である。
このマクロはplaceに格納されている数を1だけ、または指定されている 場合はxだけ減らす。
このマクロはplaceに格納されているリストの最初の要素を取り除いて
戻す。それは
(prog1 (car place) (setf place (cdr place)))
に類似しているが、すべての部分フォームを一度だけ評価するように注意する
点が異なる。
このマクロはplaceに格納されるリストの先頭にxを挿入する。
それは(setf place (cons(コンス) x place))に
類似しているが、部分フォームの評価が異なる。
このマクロはplaceに格納されているリストの先頭にxを
挿入するが、xがリストの存在するどの要素にもeqlでない
場合に限られる。
付加キーワード引数はadjoinと同様に解釈される。
See 集合としてのリスト.
このマクロは左へ1つplaceをシフトし、newvalueの値(それは
単なる汎変数ではなく、どんなLisp式でもよい)をシフトして入れ、最初の
placeからシフトして出された値を戻す。したがって、
(shiftf a b c d)は以下と同等だが
(prog1
a
(psetf a b
b c
c d))
a、b、そしてcの部分フォームは明白な順序でそれぞれ 一度だけ実際には評価される点が異なる。
このマクロは循環的にplaceを左へ一つ回転する。したがって、
(rotatef a b c d)は以下と同等だが
(psetf a b
b c
c d
d a)
部分フォームの評価が異なる。rotatefは常にnilを戻す。
(rotatef a b)はaとbを便利に
交換することに注意せよ。
下記のマクロはこのパッケージのために発明された; これらはCommon Lispに 類似するものはない。
このマクロはletに類似しているが、単なるシンボルではなく
汎変数用である。それぞれのbindingはフォーム
(place value)であるべきである; placeの
オリジナルの内容はセーブされ、valueがそれらに格納され、それから
本体formが実行される。その後、placesはオリジナルの
セーブされた内容へ設定し戻される。この大掃除は、formが
throwまたはエラーのために正規でない脱出をした場合ですら起こる。
たとえば、
(letf (((point) (point-min))
(a 17))
...)
はバッファの先頭へ現バッファの“ポイント”を動かし、17へaを
束縛する(通常のletと同様だが、aが単なる通常の
変数だからである)。本体が脱出した後、aはそのオリジナルの値に
設定し戻され、ポイントはそのオリジナルの位置へ戻る。
(point)のletfはsave-excursionとはあまり似ていない
ことに注意せよ。なぜなら後者はバッファ内の挿入と削除を追跡するマーカを
効果的にセーブするからである。実際は、(point-marker)の
letfはこの振る舞いにずっと近い(pointと
point-markerはsetf場所としては同等である; どちらも格納値
として整数かマーカを受け入れる)。
汎変数はリストのように見えるため、bindingとして‘(foo nil)’
のために‘foo’を使用するletの簡略表記法はletf
ではあいまいになるので許されていない。
しかし、binding指定子は1要素のリスト‘(place)’でもよく、
それは‘(place place)’に類似している。言い換えれば、
placeは本体へ入ることで乱されず、letfの効果はその後
placeのオリジナルの値を戻すことだけである
((place place)の例により示唆された冗長なアクセスと
格納は実際には起こらない)。
多くの場合、placeはletfフォームに入るときによく定義された
値を持たなければならない。例外は単純変数とsymbol-valueや
symbol-functionへの呼び出しだけである。入るときにシンボルが束縛
されていない場合、脱出時にmakunboundまたはfmakunboundで
単に未束縛にされる。
let*がletに対応するように、このマクロはletfに対応
する: それは並列の順序ではなく順次に束縛を行なう。
これは“汎用”修正マクロである。functionを呼び出す。
functionは引用符のない関数名、マクロ名、または
ラムダでなければならない。引数としてplaceとargsを渡し、
placeへ結果を代入し戻す。たとえば、
(incf place n)は(callf + place n)
と同じである。さらにいくつかの例:
(callf abs my-number) (callf concat (buffer-name) "<" (int-to-string n) ">") (callf union happy-people (list joe bob) :test 'same-person)
See setf独自化, define-modify-macro、修正マクロのための幾分
簡潔な表記法を作るための方法。callfは標準Common Lispへの拡張で
あることに再度注意せよ。
このマクロはcallfに似ているが、placeが関数の第1ではなく
第2引数である点が異なる。たとえば、
(push x place)は
(callf2 cons x place)と同等である。
callfやcallf2マクロは、incf、pushnew、
そしてdefine-modify-macroのような他のマクロのための
ビルディングブロックとして役に立つ。letfやletf*マクロは
シンボルマクロの処理に使われる; see マクロ束縛.