練習問題3.5
この問題は、練習問題3.4で定義したオブジェクトおよび擬似関数を用いて解く。それらの擬似関数などを以下に示す。
束縛
順序対(var, val)で表す。ここで、varは変数、valは値である。
部分環境
順序対(A, R)であり、[]による記法で表す。ここで、Aは同変数の束縛のクラス、RはA上の順序関係である。また、[]には宣言の新しい順に束縛が並ぶ。
[(x, 1), (x, 3)]
環境(全体環境)
部分環境の和クラスであり、[]と⊕とによる記法で表す。
[(x, 1), (x, 3)]⊕[(y, 1)]
宣言関数𝔇
環境Envと宣言による束縛のクラスとから新しい環境Env'を選ぶ。
Env' = 𝔇(Env, {(var₀, val₀), ..., (varₙ, valₙ)})
評価関数𝔈
式exprを環境Envで評価する。
val = 𝔈(expr, Env)
以下の答案では、本問の2種類の宣言のうち、xとyとを同時に宣言するものを同時宣言と呼び、xを宣言した後にyを宣言するものを逐次宣言と呼ぶ。また、初期の大域環境Envを空[]とする。
同時宣言
同時宣言後の大域環境Envₚ'は、
Envₚ' = 𝔇(Env, {(x, 𝔈(e₁, Env)), (y, 𝔈(e₂, Env))})
= {(x, 𝔈(e₁, Env)), (y, 𝔈(e₂, Env))} ⇢ []
= [(x, 𝔈(e₁, Env))] ⊕ [(y, 𝔈(e₂, Env))]
となる。
逐次宣言
xについての宣言後の大域環境Envₛ'は、
Envₛ' = 𝔇(Env, {(x, 𝔈(e₁, Env))})
= {(x, 𝔈(e₁, Env))} ⇢ []
= [(x, 𝔈(e₁, Env))]
となり、yについての宣言後の大域環境Envₛ''は、
Envₛ'' = 𝔇(Envₛ', {(y, 𝔈(e₂, Envₛ'))})
= 𝔇([(x, 𝔈(e₁, Env))], {(y, 𝔈(e₂, [(x, 𝔈(e₁, Env))]))})
= {(y, 𝔈(e₂, [(x, 𝔈(e₁, Env))]))} ⇢ [(x, 𝔈(e₁, Env))]
= [(x, 𝔈(e₁, Env))] ⊕ [(y, 𝔈(e₂, [(x, 𝔈(e₁, Env))]))]
となる。
以上から相違点をまとめる。
答え: 同時宣言と逐次宣言とは、yに束縛される値が式e₂を評価したものである点は同じだが、その式e₂を評価する大域環境が異なる。
より詳細には、同時宣言では初期の大域環境で式e₂が評価される。一方、逐次宣言では、変数xと式e₁の値との束縛が初期の大域環境に追加された大域環境で式e₂が評価される。
感想
正解
どうにも正解の確信が持てずモヤモヤする。原因はlet定義にあるのだろう。
いまさらだが、let定義は式ではない。式ではないのなら何なのだろう。テキストでは、OCamlのプログラムの実行とは、式を評価して値を求めることだ、との説明がなされていた。
それならば式でないlet定義は、少なくとも"普通"のプログラムの実行ではなく、何か"特別"な動作なのだろうか。そういえば、let定義が対象とする大域環境も、OCamlでは明示的に扱えない。このあたりがモヤモヤの原因か。
つまり、問題の2つのlet定義は違いがあるものの、その違いは外部には現れない。現れるのはプログラムが実行され、let定義されたyが評価されたときだが、そこまでは問題に含まれていない。なんのことはない、目に見える明確な違いを示してスッキリしたいのだが、それができないからモヤモヤしていただけか。
let定義
そもそもlet定義は必要なのだろうか。変数の定義は、let式があればこと足りるように思える。なぜなら、let定義だけ行うプログラムというのはありえない。必ずlet定義した変数を評価するはずだ。ならば、その評価のときにlet式を使えばよいのだ。もっといえば、プログラムの全部を1つの大きなlet式で覆ってしまえばよい。
計算という点、OCamlでいうところの式の評価という点からは、let定義は不要に思える。必要となるのは、対話式のインターフェイスなどでだろう。let定義は、プログラマの便宜を図るために、実用性の観点から導入された仕組みなのだろうか。
また、式の評価(値)が文脈に左右されるのはどうにも気持ちが悪い。例えば、関数fを、
let f x = (f x) + 1
と定義した場合、再定義の回数によって、
f 0 = ?
が異なる。これでは、対話式でうっかりミスして再定義した場合には、原因不明のバグに悩まされることになる。せめて、大域環境をダンプできればチェックのしようもあるのだが。
とはいえ、この問題を解くまでは、何の疑問もなく使ってきた。気にしなければ、便利な仕組みなのだが。
上記は、プログラミングinOCaml,五十嵐淳についての感想および練習問題の答案である。著作権を侵害してしまうことがないように問題文は載せていない。ただし、問題文中において、ごく短い文であって、ありふれた表現であり、それのみでは問題としての意味をなさないようなもの(例えば、"- - 1"など)は、著作物にあたらないと判断し、記述している。