Factorに入門する(9) マクロでFizzBuzz

[ Factor プログラミング言語 ]

Factor入門第9回。またFizzBuzzかよ。Factorは今時の言語なので、Lisp的なマクロがあります。

マクロの実例。

( scratchpad ) : ++ ( x -- x ) 1 + ;
( scratchpad ) 2 ++ .
3
( scratchpad ) MACRO: macro++ ( x -- x ) [ 1 + ] ;
( scratchpad ) 2 macro++ .
3
( scratchpad ) 

見た目は普通のword定義に似ています。違いは、quotationをかえすように書かなくてはいけないところ。実行結果はふつうのwordと同じ。

では何が違うのか? というと、

A call of a macro inside a word definition is replaced with the quotation expansion at compile-time if precisely the following conditions hold:
- All inputs to the macro call are literal
- The word calling the macro has a static stack effect
- The expansion quotation produced by the macro has a static stack effect
If any of these conditions fail to hold, the macro will still work, but expansion will be performed at run-time.

とのことで、入力がリテラル・マクロを呼ぶwordのスタックエフェクトがstatic・かつマクロが生成するquotationのスタックエフェクトもstaticのときに、コンパイル時に展開されるそうです。

さて、FizzBuzzをマクロで書き直してみます。friedバージョンを書き直しましょう。

IN: fizzbuzz
USING: macros kernel io math math.parser prettyprint sequences fry ;

: modN? ( x n -- ? ) mod 0 = ;
MACRO: fb ( x n str -- x/str )
    pick number?
    [ '[ _ dup _ modN? [ drop _ ] when ] ]
    [ '[ _ _ _ 2drop ] ]
    if ;

: pp ( x/str -- ) dup number? [ number>string ] when print ;
    
100 [ 1 + 15 "FizzBuzz" fb 3 "Fizz" fb 5 "Buzz" fb pp ] each

ま、これでも動くんですが、「引数がすべてリテラル」の条件が満たせてないので、速度のメリットもないですね。マクロについてはまた改めてとりあげようと思います。

トラックバック

このエントリーのトラックバックURL:
http://www.skoji.jp/mtbin/mt-tb.cgi/1222

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)