2021/10/05
無限cxr
「car
とcdr
の合成 (car
, caddr
, cadddr
,...)って4段階までしか無いのか」ってツイートを見かけたので、無限に合成されるのを作ってみた。
あらかじめ定義しておかなくても、ソースコードを読んだ時点で展開されるので、
いくらでも長いc[ad]+r
を使える。
これを使えば『Land of Lisp』のビリーとボブの会話も実行できるぞ!
(setf *readtable* *cxr-readtable*) ;;「ジブラルドルのエメラルド」が今週末に超特急列車で運搬される (defparameter *train* '((controls) (empty security-camera) (gem) (empty guard1 empty empty guard2) (passenger-seat passenger-seat passenger-seat passenger-seat))) ;; こう言えばいいかな。ブツは列車のCADDRにある (caddr *train*) ; => GEM ;; それからセキュリティカメラが、つまり、列車のCADADRにある。 (cadadr *train*) ; => SECURITY-CAMERA ;; ここに、列車のCADDDDRに乗れる乗車券を買ってあるから (caddddr *train*) ; => (PASSENGER-SEAT PASSENGER-SEAT PASSENGER-SEAT PASSENGER-SEAT) ;; でもこのCADADDDRとCADDDDADDDRにいる警備員はどうするのさ??? (list (cadadddr *train*) (caddddadddr *train*)) ; => (GUARD1 GUARD2)
なお、これを作ってたら"Land of Lisp"翻訳版のtypoに気づいた (最後のDが一個多かった)。やはり文中のコードは全て実行して検証すべきであるな。
ちなみにこの実装だと、クオートされたリテラル中にcaadddaddar
みたいのが出てきた時にちょっとまずいことになる。それを回避するにはcxr-reader
中で無理くりシンボルへの束縛を作っちゃう手がある。例えば expand-cxr
を下のものと入れ替える。
ただ、規格上、マクロ文字リーダは(streamから読む以外の)副作用を持ってはならない、とされているので、厳密にはよくない。とはいえその規程はリスタートなどで複数回リーダが呼ばれた場合に動作を保証するためのものなので、冪等な副作用なら問題にはならないだろう。
Tags: Lisp, CommonLisp, LandOfLisp
Post a comment