Next: , Previous: , Up: 汎変数   [Contents][Index]


4.2.2 修正マクロ

このパッケージはsetfの他にも、汎変数に作用する多くのマクロを 定義する。placeが単に変数名である場合でも、多くは興味深く 有用である。

Special Form: psetf [place form]…

psetqsetqに対応するように、このマクロはsetfに 対応する: いくつかのplaceformを含むとき、代入は 順次にではなく並列に起こる。つまり、すべての部分フォームは左から右へ 評価され、それからすべての代入が(未定義の順序で)行なわれる。

Special Form: incf place &optional x

このマクロは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)と本質的に同等である。

Special Form: decf place &optional x

このマクロはplaceに格納されている数を1だけ、または指定されている 場合はxだけ減らす。

Special Form: pop place

このマクロはplaceに格納されているリストの最初の要素を取り除いて 戻す。それは (prog1 (car place) (setf place (cdr place))) に類似しているが、すべての部分フォームを一度だけ評価するように注意する 点が異なる。

Special Form: push x place

このマクロはplaceに格納されるリストの先頭にxを挿入する。 それは(setf place (cons(コンス) x place))に 類似しているが、部分フォームの評価が異なる。

Special Form: pushnew x place &key :test :test-not :key

このマクロはplaceに格納されているリストの先頭にxを 挿入するが、xがリストの存在するどの要素にもeqlでない 場合に限られる。

付加キーワード引数はadjoinと同様に解釈される。 See 集合としてのリスト.

Special Form: shiftf place… newvalue

このマクロは左へ1つplaceをシフトし、newvalueの値(それは 単なる汎変数ではなく、どんなLisp式でもよい)をシフトして入れ、最初の placeからシフトして出された値を戻す。したがって、 (shiftf a b c d)は以下と同等だが

(prog1
    a
  (psetf a b
         b c
         c d))

ab、そしてcの部分フォームは明白な順序でそれぞれ 一度だけ実際には評価される点が異なる。

Special Form: rotatef place…

このマクロは循環的にplaceを左へ一つ回転する。したがって、 (rotatef a b c d)は以下と同等だが

(psetf a b
       b c
       c d
       d a)

部分フォームの評価が異なる。rotatefは常にnilを戻す。 (rotatef a b)abを便利に 交換することに注意せよ。

下記のマクロはこのパッケージのために発明された; これらはCommon Lispに 類似するものはない。

Special Form: letf (bindings…) forms…

このマクロはletに類似しているが、単なるシンボルではなく 汎変数用である。それぞれのbindingはフォーム (place value)であるべきである; placeの オリジナルの内容はセーブされ、valueがそれらに格納され、それから 本体formが実行される。その後、placesはオリジナルの セーブされた内容へ設定し戻される。この大掃除は、formthrowまたはエラーのために正規でない脱出をした場合ですら起こる。

たとえば、

(letf (((point) (point-min))
       (a 17))
  ...)

はバッファの先頭へ現バッファの“ポイント”を動かし、17へaを 束縛する(通常のletと同様だが、aが単なる通常の 変数だからである)。本体が脱出した後、aはそのオリジナルの値に 設定し戻され、ポイントはそのオリジナルの位置へ戻る。

(point)letfsave-excursionとはあまり似ていない ことに注意せよ。なぜなら後者はバッファ内の挿入と削除を追跡するマーカを 効果的にセーブするからである。実際は、(point-marker)letfはこの振る舞いにずっと近い(pointpoint-markersetf場所としては同等である; どちらも格納値 として整数かマーカを受け入れる)。

汎変数はリストのように見えるため、bindingとして‘(foo nil)’ のために‘foo’を使用するletの簡略表記法はletf ではあいまいになるので許されていない。

しかし、binding指定子は1要素のリスト‘(place)’でもよく、 それは‘(place place)’に類似している。言い換えれば、 placeは本体へ入ることで乱されず、letfの効果はその後 placeのオリジナルの値を戻すことだけである ((place place)の例により示唆された冗長なアクセスと 格納は実際には起こらない)。

多くの場合、placeletfフォームに入るときによく定義された 値を持たなければならない。例外は単純変数とsymbol-valuesymbol-functionへの呼び出しだけである。入るときにシンボルが束縛 されていない場合、脱出時にmakunboundまたはfmakunboundで 単に未束縛にされる。

Special Form: letf* (bindings…) forms…

let*letに対応するように、このマクロはletfに対応 する: それは並列の順序ではなく順次に束縛を行なう。

Special Form: callf function place args

これは“汎用”修正マクロである。functionを呼び出す。 functionは引用符のない関数名、マクロ名、または ラムダでなければならない。引数としてplaceargsを渡し、 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への拡張で あることに再度注意せよ。

Special Form: callf2 function arg1 place args

このマクロはcallfに似ているが、placeが関数の第1ではなく 第2引数である点が異なる。たとえば、 (push x place)(callf2 cons x place)と同等である。

callfcallf2マクロは、incfpushnew、 そしてdefine-modify-macroのような他のマクロのための ビルディングブロックとして役に立つ。letfletf*マクロは シンボルマクロの処理に使われる; see マクロ束縛.


Next: , Previous: , Up: 汎変数   [Contents][Index]