読者です 読者をやめる 読者になる 読者になる

@uents blog

Code wins arguments.

SICP 読書ノート#28 - 3.2 評価の環境モデル (pp.138-147)

SICP Scheme

前回からずいぶん間が空いてしまった。

今回は「§3.2 評価の環境モデル」から。

初出じゃないけど用語がいろいろと出てくる。

  • 環境(environments)
  • フレーム(frames)
  • 束縛(bindings)
  • 大域(global)
  • 外側の環境(enclosing environment)
  • 変数の値(value of a variable)
  • 未束縛(unbound)
  • (束縛を)隠す(shadow)

何のことやらさっぱりという人は、 「§1.1 名前と環境」から 読み返すといいかもしれない。

評価の規則

すでに何度か出ている話題だけど、

(define (square x)
  (* x x)

は、

(define square
  (lambda (x) (* x x)))

のsyntax sugarである。

つまり、(define (square x) (* x x))というのは、 (* x x) 手続きをsquareという変数に束縛しているにすぎない。

トップレベルで上記の式を評価すると、squareは大域環境に束縛されるので、 テキスト図3.2のような例になる。

image

単純な手続きの作用

(square 5)

という式が評価されると、x : 5という束縛関係をもった環境が 生成されるが、これは大域環境ではなく手続きの実行時のみに生成される 一時的な環境である。テキスト図3.3のE1がそれ。 また、これは``E1```の外部からは参照できないローカルな環境でもある。

image

逆に、E1から大域環境を参照することは可能である。 グローバル→ローカルへは参照できないが、ローカル→グローバルへは参照できる。

よって、図3.3ではE1から大域環境へと矢印が引いてある。 JavaScriptでのスコープチェーンと同じ概念だ(と思う)。

問題 3.9

(factorial 3)の実行過程。(factorial 6)を描くのはさすがに大変だったので...

image

局所変数の入れ物としてのフレーム

図3.3のE1のxも局所変数だけれど、squareの実行時にしか現れないため 状態を保持する入れ物としては使えない。

しかし、以下のような手続きに対し、

(define (make-withdraw balance)
  (lambda (amount)
    (if (>= balance amount)
        (begin (set! balance (- balance amount))
               balance)
        "Insufficient funds")))

その戻り値の手続きオブジェクトをある変数に束縛すると、 この手続きオブジェクトは外部の環境にあるbalanceを参照するため、 その結果、この手続きオブジェクトが解放されない限り、 balanceを含む環境も解放されないため、状態を保持する入れ物として使える。 まさにクロージャだ。

image

問題 3.10

(define W2 (make-withdraw 100)) まで評価が終わったタイミングでの実行結果。

環境構造としては initial-amount の値がローカル環境に保持される点が、 テキストの前述の例とは異なる。

image

内部定義

さらに進んで手続きの中にローカルな手続きをもつ場合の例。 これまでの延長線で考えればよいので、特筆すべきことなし。

問題 3.11

(define acc (make-account 50)) 評価時。

image

((acc 'deposit) 40) 評価時。

image

(define acc2 (make-account 100)) 評価時。

image

次は「§3.3 可変データのモデル化」から。


※「SICP読書ノート」の目次はこちら