問題4-1

第四章「超言語的抽象(metalinguistic abstraction)」に入りました。本章の冒頭では、いきなり野心的なことが述べられています。

新しい言語を創設する超言語的抽象は、工学的設計のすべての分野で重要な役割を果す。これはプログラミングにおいて、新しい言語が形式化出来るだけでなく、評価器を構築してこれらの言語を実装し得るが故に、特に計算機のプログラミングで重要である。プログラム言語の評価器(evaluator)(または解釈系(interpreter))とは、その言語の式に作用させられると、その式を評価するのに必要な行動を実行する手続きのことである。
これをプログラミングの最も基本的な考えと見るのは決して誇張ではない:

  • プログラム言語での式の意味を決定する評価器は、もう一つのプログラムに過ぎない

この点を認めるのはプログラマとしてのわれわれ自身の見方を変えることである。われわれは他人が設計した言語の利用者であるよりは、言語の設計者として自分を見るようになる。

そこで第一節では、Lisp自身の評価器を構成していくようです。evalとapply、評価と作用をapply-primitive-procedureできるようになるまで繰り返していくようなeval/apply手続きが定義されていて、その中の細かい処理が20ページくらいに渡って述べられています。長い道のりになりそうですが、着実に前へ進んでいきたいと思っています。
問題4-1。eval内で、演算子に引数を作用させる部分の実装について問われています。引数のリストであるlist-of-valuesが、どのような順序でoperatorがapplyされるのか、本文の手続きでは明確ではないので、それをはっきりさせるような手続きを書けとのことです。iterator的な反復ロジックを書いて、listを操作するようにすればいいのかなと思いましたが、結局どこかでconsが出てきて、上手くいきそうにありません。そこで、ここのブログを見たら、以下のような手続きで実装されていました。letで束縛している処理の方が、先に評価されるということでしょうか。

(define (list-of-values-lr exps env)
  (if (no-operands? exps)
    '()
    (let ((first (eval (first-operand exps) env)))
      (cons first (list-of-values-lr (rest-operands exps) env)))))

(define (list-of-values-rl exps env)
  (if (no-operands? exps)
    '()
    (let ((rest (list-of-values-rl (rest-operands exps) env)))
      (cons (eval (first-operand exps) env) rest))))