はじめてのリードマクロ

リーダーマクロ?リードマクロ?
まあとりあえず、リー○マクロを少しだけ触ってみました。
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