marco その2

これの続き>http://d.hatena.ne.jp/nishiohirokazu/20080319/1205923818

gosh> (define-syntax chain (syntax-rules ()
	((chain arg func) (func arg))
	((chain arg func ...)  
	 (chain (func arg) ...))))
#<undef>
gosh> (macroexpand '(chain 1 inc inc inc))
(((inc 1) #0=(inc 1)) ((inc 1) #0#))

ぎゃあ。
「...」の挙動が期待と違うみたいだ。

gosh> (macroexpand '(chain 1 inc))
(inc 1)
gosh> (macroexpand '(chain 1 inc inc))
((inc 1) (inc 1))
gosh> (macroexpand '(chain 1 foo bar))
((bar 1) (foo 1))

ふむ。

gosh> (define-syntax chain (syntax-rules ()
	((chain arg func) (func arg))
	((chain arg func ...)  
	 (quux (func arg) ...))))


gosh> (macroexpand '(chain 1 foo bar))
(#<identifier user#quux> (foo 1) (bar 1))

そうか。

gosh> (macroexpand '(chain 1 foo bar))
(#<identifier user#quux> (foo 1) (bar 1))
gosh> (define-syntax t0 (syntax-rules ()
	((t0 a b ...) ((+ a b) ...)))
)
#<undef>
gosh> (macroexpand '(t0 1 2 3 4 5 6))           
((#0=#<identifier user#+> 1 2) (#0# 1 3) (#0# 1 4) (#0# 1 5) (#0# 1 6))
gosh> +
#<subr +>
gosh> (define-syntax t1 (syntax-rules ()
	((t1 (a b) ...) ((+ a b) ...))))
#<undef>
gosh> (macroexpand '(t1 (1 2) (3 4) (5 6)))
((#0=#<identifier user#+> 1 2) (#0# 3 4) (#0# 5 6))

なるほど。「...」は単に不定個のものとマッチする表現かと思ってたけど違ったようだ。

gosh> (define-syntax chain (syntax-rules ()
	((chain arg func) (func arg))
	((chain arg func rest ...)  
	 (chain (func arg) rest ...))))
#<undef>
gosh> (macroexpand '(chain 1 inc inc inc))
(inc (inc (inc 1)))

けっきょくid:hayamizのと同じになってしまった。

        • -

ところでやりたかったことはとarg.foo().bar().baz()という文字列をパースして(foo (bar (baz arg)))というツリーを作った上でevalするってことができるはずで、それにはたぶんreader-macroとか言うものを使うんだろう。ということでとりあえずmacroの勉強をしてみたのだ。

gosh> (define (facto n)
	(if (= n 0)
		1
		(* n (facto (- n 1)))))
facto
gosh> (facto 5)
120