comp.lang.schemeのポストより:
次のコードが何をするか、コードを走らせることなく述べよ。 (let* ((yin ((lambda (foo) (newline) foo) (call/cc (lambda (bar) bar)))) (yang ((lambda (foo) (write-char #\*) foo) (call/cc (lambda (bar) bar))))) (yin yang))
くれぐれも、自分で考える前にgoshに上の式を打ち込まないように!
正解はTaylor Campbellのポストにある。
以下は回答に触れるので、自力で解きたい人は注意。 なお、答えを確かめるにはgoshではなくguileを使うべし。 その理由は以下に述べる。
Shiroが最初に考えた回答は、 Taylor Campbellの最初のポスト(誤り) と同じだった。 つまり、最初にnewline, '*', newlineと来て、あとはずっと'*'が出力される、 というもの。
で、goshで実行してみると、確かにその通りになる。 だが、実はそれは正しくなかったのだ。
正解は一行にひとつづつ'*'が増えて行くというもので、 guileで実行すれば確かにそうなる。
というわけで、Shiroにとっての問題は、Gaucheのどこがおかしいのか? ということになったわけだ。
Gaucheでも、let*をlambdaに手で展開すると正しい出力が得られる。
((lambda (yin) ((lambda (yang) (yin yang)) ((lambda (foo) (write-char #\*) foo) (call/cc (lambda (bar) bar))))) ((lambda (foo) (newline) foo) (call/cc (lambda (bar) bar))))
しかし、Gaucheのコンパイラはlet系の構文はlambdaへとは展開せず、 専用のインストラクションへとコンパイルしている。 そのへんがまずいらしい。
※現在のバージョン(0.8.7)のgoshで実行すると正しい結果を得られる。2006/08/01 04:28:13 PDT