Factorに入門する(8) dip combinatorsを駆使してFizzBuzzを書く
Factor入門第8回。今回は、Factorに多々あるcombinatorのうち、"dip combinators"について調べます。factorのcombinatorとは、combinatory logicでいうcombinatorのようなのですが、これを調べるのは、また後日。先に実例で理解しましょう。
ではdipです。documentの説明をみてみましょう。
The dip combinators invoke the quotation at the top of the stack, hiding the values underneath:
よくわからんですね。試してみましょう。
( scratchpad ) 1 2 3 [ / ] dip --- Data stack: 1/2 3 ( scratchpad ) clear ( scratchpad ) 1 2 3 4 [ / ] 2dip --- Data stack: 1/2 3 4 ( scratchpad )
dipは、「スタックトップのquotationを実行する。ただし、quotationの下にある値はいったんどけておき、quotation実行後に戻す。という動作をしています。dipのstack effectは( x quot -- x )となっていますが、この"x"がどけておく値ですね。
2dipの場合は、quotationの下にある値2つをどけています。この「どけておく先」を、factorでは"retain stack"といっているようです。
さて、前回にひきつづきFizzBuzz。dipをつかって書き直してみます。
IN: fizzbuzz USING: kernel io math math.parser prettyprint sequences fry ; : modN? ( x n -- ? ) mod 0 = ; : fb ( x n str -- x/str ) pick number? [ pick [ modN? ] 2dip ? ] [ 2drop ] if ; : pp ( x/str -- ) dup number? [ number>string ] when print ; 100 [ 1 + 15 "FizzBuzz" fb 3 "Fizz" fb 5 "Buzz" fb pp ] each
前回とはword fb見た目がまったく違います。よりシンプルですが、pickして2dipして?、って流れは、ちょっと考えないとおいて行かれます。fried quotationに比べるとトリッキーな感じです。
このコード例はこの記事にそっくりなのは偶然、ではなく、先にカンニングしていたからです。
FizzBuzzを最初に書いた後、他に書いてるひとはいないかな? と思って探してみつけました。しかしその時点では2dipが分からなくて読めず。ようやく、自力で2dipがつかえるところに辿り着きましたよ。