関数型言語の勉強にSICPを読もう - (69) 4章 - 超言語的抽象228ページ) C++でSchemeインタプリタを作ろう18
バグ修正。
(define a 3) (define a 4)
とした場合に a の値がおかしくなってしまう件を調査。
Gaucheで試したところ普通に上書きされたので、たぶん上書きで良いと思ったが、Schemeの仕様上どういう扱いだったか?を調べるためにR5RS(PDF)を読んでみた。
全部で50ページくらいあって18ページ位まで読んだ。
プログラムのトップ・レベルでは,定義
(define <変数> <式>)
は,もし<変数> が束縛されているならば,本質的に代入式
(set! <変数> <式>)
と同じ効果をもつ。しかし,もし<変数> が未束縛ならば,
この定義は代入を実行する前にまず<変数> を新しい場所に
束縛する。しかるにset! を未束縛の変数に対して実行する
とエラーになるだろう。
(define add3
(lambda (x) (+ x 3)))
set!と同じで良いのか。
で、該当部は void Environment::defineVariable(Variable* variable, Object* value)。
2つ間違いをしていた。
- 一番深いフレームに対して define しなくてはならないところ一番浅いところでやっていた。→単純なミス
- map::insertは、値をうわがいてくれると勘違いしていた。→ミス
これを修正したらきちんと動作するようになった。
ついでに test.scm で数々のテストを通してコミットした。爽快!。
18ページあたりまでのR5RSの感想とか勘違いしていたところ。
継続とか末尾再帰はやっぱりまだきちんと理解できていないことがわかった。マクロも怪しい。
オブジェクトが占める記憶領域を再利用してよい。これが,
Scheme の実装が(たいていの場合には!) 記憶領域を使い果
たさない理由である
GCが必須とは書いていない!
規約により,つねにブーリアン値を返す手続きの名前は普通
“?” で終わる。このような手続きは述語(predicate) と呼ば
れる。
規約により,以前に割り付けられた場所の中へ値を格納す
る手続き(3.4 節参照) の名前は普通“!” で終わる。このよ
うな手続きは書換え手続き(mutation procedure) と呼ばれ
る。規約により,書換え手続きが返す値は未規定である。
なるほど。
英字の大文字と小文字は,文字定数と文字列定数の中を除い
て,決して区別されない。たとえばFoo はFOO と同じ識別
子であり,#x1AB は#X1ab と同じ数である。
これは直さないとな。
どのオブジェクトも下記の述語を二つ以上満たすことはない。
boolean? pair?
symbol? number?
char? string?
vector? port?
procedure?
なんだってー。 boolean?かつnumber?を満たしてしまっているかも。
どう区別しようか。