kiyoka.2009_06_15 RSSPLAIN

Related pages: !kiyoka.blog.list !kiyoka.blog.2009_06
35554455555555555555555555555555555555555543444444544444544445213
3

[Nendo] 伝統的なmacroが動いた

5

ここまで長い道程だったが、macroが動いた。

5

実際にmacroを実装してみるとmacroがどういうものかやっと理解できた気がする。

5

 

4

伝統的なmacroの例

4

 

5
 引数に指定された変数をインクリメントするmacroを定義
5
nendo> (define inc (macro (x) (list 'set! x (list '+ '1 x))))
5
#<LispMacro:0x00083fcc@(stdin):1>
5

 

5
 変数aを準備
5
nendo> (define a 10)
5
10
5

 

5
 macroの展開結果を見る
5
nendo> (macroexpand1 '(inc a))
5
(set! a (+ 1 a))
5

 

5
 実際にインクリメントしてみる
5
nendo> (inc a)
5
11
5

 

5
 引数に指定した処理を2回実行するmacroを定義
5
nendo> (define twice (macro (x) (list 'begin x x)))
5
#<LispMacro:0x000720d8@(stdin):6>
5

 

5
 (inc a)をマクロで2回実行
5
nendo> (twice (inc a))
5
13
5

 

5
 macroの展開結果を見る(1回だけマクロ展開)
5
nendo> (macroexpand1 '(twice (inc a)))
5
(begin (inc a) (inc a))
5

 

5
 macroの展開結果を見る(2回のマクロ展開)
5
nendo> (macroexpand1 (macroexpand1 '(twice (inc a))))
5
(begin (set! a (+ 1 a)) (set! a (+ 1 a)))
5

 

5

さて、orとandをmacroで実装してみよう。と思ったが、可変長引数をサポートしていないので、書けないという問題に気がついた。orz.

5

やっぱり可変長引数は必須なのか...

5

 

5

 

4

macroの可変長引数サポートについて

3

その後、macroに可変長引数をサポートしようとして,

4
(define name (macro (arg1 arg2) body))
4

という形式ではゼロ個以上の可変長引数がサポートできないことが分かった... o.rz.

4

要するに、lambdaが入る部分にmacroというキーワードが入る形で考えていた。

4

そうすると、なにが問題かというと、ゼロ個以上の可変長引数を書きたい場合は、気持ち的には

4
(define name (macro (. rest) body))
4

だが、S式として成立しない。 (. rest) の部分がS式としてエラーとなる。

5

 

4

TinySchemeはmacro定義をつぎの形式で行なうが、この形式ならうまくいく。

4
(macro (name arg1 arg2) body)
4

または、

4
(macro name (lambda (arg1 arg2) body)
4

となっている。

5

 

4

この形式なら

4
(macro (name . rest) body)
4

とかけるのね。

4

つまり、defineと同じイメージでmacroキーワードを組み立てないといけないのだな。

5

 

2

COMMENTshiro

(macro rest body) じゃまずいですか? > ゼロ個以上の可変長引数

1

COMMENTkiyoka

> (macro rest body) じゃまずいですか?

おっと、今R5RSの仕様をみたら、lambdaがその形式を取るんですね。

初めて知りました。

macroも同じ形式で問題ないです。

というか、lambdaのほうもその形式をサポートしないといけないですね。

ありがとうございます。

3

...comment disabled...