Posted 2018-12-07 18:38:26 GMT
《 Lisp SETF Advent Calendar 2018 8日目 》
実践編今回は、defsetf
の長形式篇です。
前回、defsetf
の短形式を紹介しましたが、短形式では、引数の順番等の条件がうまく嵌ればとても簡潔に書けます。
しかし、そうはいかない場合もあるのと、仮引数で&optional
、&key
等々と指定したい場合にdefsetf
の長形式を使うことになります。
短形式と同じ例ですが、こんなゲッターとセッターの対があった場合、
(defun kar (list)
(car list))(defun set-kar (list val)
(rplaca list val))
(let ((u (list 0 1 2)))
(set-kar u 42)
(list u (kar u)))
→ ((42 1 2) 42)
(defsetf kar (list) (val)
`(set-kar ,list ,val))
のように、普通のマクロ定義のような感じで書けます。
(let ((u (list 0 1 2)))
(setf (kar u) 42)
(list u (kar u)))
→ ((42 1 2) 42)
引数宣言の順番も、setf
が使われる場合の引数の順番と同じなので迷うこともないでしょう。
短形式では、非常に簡潔に書けました、
(defsetf kar set-kar)
しかし、長形式で明示的に書かれていた方が判り易いですね。
defsetf
で定義できるものは基本的にセッターとゲッターが存在し、それが対称に動作しているものになります。
defsetf
で扱えないようなイレギュラーなものは、最も汎用的なsetf
定義オペレーターである、define-setf-expander
とget-setf-expansion
を駆使することになります。
アドベントカレンダーの後半ではイレギュラーなsetf
定義でも紹介していこうかなと思います。
■
HTML generated by 3bmd in LispWorks 7.0.0