まくろちゃれんじ!setf編(第3話)
setfマクロの実装は、今の段階ではちょっと無理そう。手作業である程度作れないこともないだろうけど…。
setfの仕事の内容をもう一度まとめてみる。
まず、外側から見た仕事は「あるアクセスにおいて評価されるはずの内容を他のものに変更する」というもの。つまり例えば(setf (caddr x) 10)であれば、(caddr x)の評価を10に変更するのが仕事になるし、(setf (aref x 3) 11)であれば(aref x 3)の評価を11にするのが仕事になる。
次に、実際のマクロによる変換について。
> (macroexpand '(setf (aref x 3) 11)) (system:*aset x 11 3) > (macroexpand '(setf (cdr x) 11)) (progn (rplacd x 11) 11) > (macroexpand '(setf (cadr x) 11)) (progn (rplaca (cdr x) 11) 11) > (macroexpand '(setf x 11)) (setq x 11) > (macroexpand '(setf (nth 10 x) 11)) (progn (rplaca (nthcdr 10 x) 11) 11) > (macroexpand '(setf (tenth x) 11)) (progn (rplaca (nthcdr 9 x) 11) 11)
このように、アクセス方法を示す関数*1次第でsetfによる変換の方法が異なっていることが分かる。また何番目の要素かを示す~thとnthとは本質的に同じ関数であることも分かる。
onLisp12章によるとアクセス関数からアクセス方法を取り出すことをインヴァージョンと言っているように見える。そうだとすれば、そのインヴァージョンを(出来れば機能として)利用することによりマクロの展開方法を考えることが出来そうである。しかし本当にそうか分からない。課題としては今後に持ち越しだ。
とりあえず、明日学校に行って電気系図書館でCommon Lispの仕様本を見てこようかな。ついでにG5のレポートの準備もしてこよう。
*1:アクセス関数