[SML 7885] Re: 継続(continuation)というスタイル

AOKI Atsushi atsushi @ cc.kyoto-su.ac.jp
2010年 12月 19日 (日) 17:16:28 JST


青木@京都宇治です。

先のメールにて、継続(コンティニュエーション・パッシング・ス
タイル)を用いて階乗計算を行うプログラムを紹介しましたが、

| factorial |
factorial :=
        [:n :continuation |
        (n isInteger not or: [n negative]) ifTrue: [^self error: 'boo!'].
        n = 0
            ifTrue: [continuation value: 1]
            ifFalse: [factorial value: n - 1 value: [:a | continuation value: a * n]].
        n halt].
factorial value: 10 value: [:a | ^a]

その実行過程をプログラム(ソースコード)として生成し、整形し、
実行し、その結果を獲得するプログラムを書き下ろしてみました。

| anInteger anInterval aStream aCode aTree aResult |
anInteger := 10.
anInterval := 0 to: anInteger.
aStream := String new writeStream.
aCode :=
        [anInterval do:
                [:n |
                | s |
                s := n printString.
                aStream nextPutAll: '| con' , s , ' | con' , s , ' := '.
                n < anInterval last
                    ifTrue: [aStream nextPutAll: '[:a' , s , ' | ']
                    ifFalse: [aStream nextPutAll: '[:a | ^a]. ']].
        anInterval reverse do:
                [:n |
                | s |
                s := n printString.
                aStream nextPutAll: 'con' , s , ' value: '.
                n > anInterval first
                    ifTrue:
                        [| r |
                        r := (n - 1) printString.
                        aStream nextPutAll: 'a' , r , ' * ' , s , ']. ']
                    ifFalse: [aStream nextPutAll: '1']].
        aStream contents]
                ensure: [aStream close].
aTree := Refactory.Browser.RBParser parseExpression: aCode.
aCode := aTree formattedCode.
aResult := Compiler evaluate: aCode.
Transcript
    clear;
    nextPutAll: aCode;
    cr;
    nextPutAll: '==> ';
    nextPutAll: aResult printString.
^aResult

トランスクリプトには次のように出力されます。conNがfactorialN
のコンティニュエーションを意味しています。

| con0 |
con0 :=
        [:a0 |
        | con1 |
        con1 :=
                [:a1 |
                | con2 |
                con2 :=
                        [:a2 |
                        | con3 |
                        con3 :=
                                [:a3 |
                                | con4 |
                                con4 :=
                                        [:a4 |
                                        | con5 |
                                        con5 :=
                                                [:a5 |
                                                | con6 |
                                                con6 :=
                                                        [:a6 |
                                                        | con7 |
                                                        con7 :=
                                                                [:a7 |
                                                                | con8 |
                                                                con8 :=
                                                                        [:a8 |
                                                                        | con9 |
                                                                        con9 :=
                                                                                [:a9 |
                                                                                | con10 |
                                                                                con10 := [:a | ^a].
                                                                                con10 value: a9 * 10].
                                                                        con9 value: a8 * 9].
                                                                con8 value: a7 * 8].
                                                        con7 value: a6 * 7].
                                                con6 value: a5 * 6].
                                        con5 value: a4 * 5].
                                con4 value: a3 * 4].
                        con3 value: a2 * 3].
                con2 value: a1 * 2].
        con1 value: a0 * 1].
con0 value: 1
==> 3628800

------------------------------------------------------------
AOKI Atsushi          http://www.cc.kyoto-su.ac.jp/~atsushi/


SML メーリングリストの案内