内部defineの振舞い
本日のSICP読書会で出た話題。問題4.19。
ubuntu% cat test.scm (display (let ((a 1)) (define (f x) (define b (+ a x)) (define a 5) (+ a b)) (f 10))) (display "\n") ubuntu% ./sscm test.scm 16 ubuntu% gosh test.scm 20 ubuntu% guile -s test.scm ERROR: Unbound variable: a ubuntu% scm test.scm SCM Turtlegraphics Copyright (C) 1992 sjm@cc.tut.fi, jtl@cc.tut.fi Type `(help-gr)' or `(help-turtlegr)' for a quick reference of the new primitives. ;While loading "test.scm", line 7: ERROR: "test.scm", line 4: unbound variable: a
原理的には内部定義は同時に起こる為、Gaucheの動きが正しい。しかしこれを満たす実装はなかなか大変である為、16を返すぐらいならunbound variable: aを返せとSICPには書いてある。確かにSigSchemeでこれに対応しようと思ったらパフォーマンス落ちそうだなぁ。どうしましょ。
Hanoi Counterが動かなくなった原因もこの問題に関連すると思われる。最初の(read)と2回目の(read)がコードの順番に実行されるという保証はどこにもない。原理的には"同時"なのだ。この場合はlet*を使用するのが無難ですな。