はじめてのリードマクロ
リーダーマクロ?リードマクロ?
まあとりあえず、リー○マクロを少しだけ触ってみました。
Lispが見かけ上Lispに見えなくなる瞬間。
Lispはカリー化が面倒なのでカリー化を補助するマクロを定義する遊び。
;; ']' をマクロの文字だと認識させる CL-USER> (set-macro-character #\] (get-macro-character #\))) T ;; '[' から ']' までを対象にマクロを定義する CL-USER> (set-macro-character #\[ #'(lambda (stream c1) (let* ((exp (read-delimited-list #\] stream t)) (fn (first exp)) (args (rest exp))) `(lambda (&rest other) (apply (function ,fn) (append (quote ,args) other))) ))) T
こうすると以下のように[〜]でカリー化できるようになる。
; ラムダ式が返ってくる CL-USER> [expt 2] #<FUNCTION :LAMBDA (&REST OTHER) (APPLY #'EXPT (APPEND '(2) OTHER))> CL-USER> ([expt 2] 10) 1024 CL-USER> ([expt] 2 8) 256 CL-USER> ([expt 2 0]) 1 CL-USER> (setq x [+ 1 2 3]) #<FUNCTION :LAMBDA (&REST OTHER) (APPLY #'+ (APPEND '(1 2 3) OTHER))> CL-USER> (funcall x 4) 10 ; マクロを展開 CL-USER> (macroexpand '[expt 2]) #'(LAMBDA (&REST OTHER) (APPLY #'EXPT (APPEND '(2) OTHER))) T
まだ少し理解できた程度だけど、適所で使えば便利そう。
使いすぎるとオレオレ言語になってしまう。
ぐぐるとrubyの構文を再現したものとか出てくるし、On Lispに載ってるPrologの実装でも恐らく使われてるんじゃないだろうか。
カリー化とか関数合成あたりはリードマクロを定義しておいてもいいかも。
個人的にはガードとかも欲しい。
あれそれなんてHaskell.
参考:http://user.ecc.u-tokyo.ac.jp/~tt076524/onlispjhtml/readMacros.html