『Scheme手習い』読書会 第15回

Scheme手習い』読書会の15回目です。範囲としては10章すべて(P176〜P193)です。

15回目と書きましたが、実は15回目と16回目を兼ねています。15回目では10章の大部分を読んだのですが、もう一度10章頭から見直したくなり、もう一度読み返すことにしたのです。最初に読んだときは書いてあることの意図がつかめず、わけが分からないままに進んでしまい、10章の終盤になって10章の意図・目的に気付いたのです。

10章の目的は関数valueの定義です。10章のすべてがこれに割かれています。valueは6章で登場した関数で、本文中では「式の自然な値を返す関数」と書かれています。6章の時点では数字を計算する程度の機能でした。10章ではこれを機能拡張し、関数を評価できるようにします。そのためのentry/table構造の作成があり、値ごとのタイプ(アクション)決定があるのです。

  • 10章 このすべての値は何だ
    • エントリ(entry):リストのペア。第一要素は集合(set)であり、第二要素は第一要素と同じ長さのリスト。.NETのDictionary、JavaのMapのようなデータ構造。
    • 関数new-entryの定義:2つの引数を取り、エントリを作成する関数。第一引数がsetかどうかの検証なども行わない。ペアを作成する関数buildの別名として定義。
    • 関数lookup-in-entryの定義:第一引数に検索する要素、第二引数に検索対象のエントリ、第三引数に見つからなかったときに呼び出される関数を渡す。
    • テーブル(table):エントリのリスト。環境とも言うらしい。
    • 関数lookup-in-tableの定義:テーブル版lookup-in-entry。lookup-in-entryを使用して定義。見つからなかったときに、次のエントリを対象に検索するようlookup-in-entryに関数を渡すところがポイント。
    • 関数valueの再定義:処理結果を確認。
    • タイプ(アクション):数や真偽値やcons,carなどは*const、quoteは*quote、変数は*identifier、lambdaは*lambda、condは*cond、その他の式は*application。
      • 空リストが定義されていないのが、私には非常に気になったため、10章終了後に空リストを*constに割り当て、うまく動作するように修正した。
    • 補助関数expression-to-actionの定義:式を受け取り、適切なアクションを返す。atomかどうかによって、atom-to-action,list-to-actionに処理を振り分ける。
    • 補助関数atom-to-actionの定義:適切なアクション(atomの場合)を返す。
    • 補助関数list-to-actionの定義:適切なアクション(listの場合)を返す。
    • 関数valueの定義:補助関数meaningに式eと空テーブルtableを渡す。
    • 補助関数meaningの定義:expression-to-actionでeの適切なアクションを返し、それに対して式eとテーブルtableを渡す。
    • 関数(アクション)*constの定義:数、真偽値はそのまま返し、それ以外は(primitive 式e)を返す。
    • 関数(アクション)*quoteの定義:式eの第二要素を返す。(quote a)ならaを返すということ。
    • 関数(アクション)*identifierの定義:tableから式eに対応する要素を探して、返す。
    • 関数(アクション)*lambdaの定義:(non-primitive テーブル 仮引数 関数本体)の形式で返す。
    • 関数(アクション)*condの定義:補助関数evconに式eの2番目以降の要素とテーブルとを渡す。
    • 補助関数evcondの定義:各行ごとにelseかどうかや条件を満たしているかを確認し、必要に応じて関数meaningを呼び出す。
      • P187の*condの例が誤っているため、読者は混乱する。詳細は正誤表参照。
    • 関数(アクション)*applicationの定義:補助関数evlisおよびapplyを使用し、任意の式を再帰的に展開していく。
    • 補助関数evlisの定義:リストを評価し、展開していく。必要に応じて関数meaningを呼び出して、結果をconsしていくだけ。
    • 補助関数applyの定義:補助関数primitive?および補助関数non-primitive?、補助関数apply-primitive、補助関数apply-closureを使用して、関数を適用する。
    • 補助関数primitive/補助関数non-primitiveの定義:式が(primitive x)の形か(non-primitive x)の形かを見て#t/#fを返す。
    • 補助関数apply-primitiveの定義:基本となる関数consやcarなどを実際に動作する関数(Schemeが元々持っているもの)を適用し結果を返す。
    • 補助関数apply-closureの定義:テーブルを拡張し、仮引数に対応する値を持つエントリを追加し、meaningを使用して、関数を適用する。
    • else はい。もう宴会の時間です。

さて、これで『Scheme手習い』の最終章が終わりました。誤字など困る部分もありましたが、Yコンビネータの定義や関数valueの定義など楽しめた部分もあり、括弧への抵抗も減り、Meadowもずいぶん使えるようになりました。良い企画だったと思います。

次は『Scheme修行』でしょうか。まだ分かりません。

最後にまとめエントリを作って、『Scheme手習い』読書会を終了したいと思います。