問題4-30

eval-sequence内で渡された式の並びに対して、一つずつactual-valueをしなければならないのではないかというCyの疑問について考えます。
aでBenが書いている手続きが、evalでも上手く動く理由としては、例え並びの要素がthunkされていたとしても、それ自身が式ならば、eval内のapplication?に引っかかり、そこで演算子がactual-valueされ、thunkタグが剥がれるので、式が正しく作用されるのではないかと考えられます。
しかし、bのp2の方の手続きは、evalだけでは上手くいきません。

(define (p2 x)
  (define (p e)
    e
    x)
  (p (set! x (cons x '(2)))))

(p2 1)

こういう式があったら、結果は、(1 2)となってほしいところですが、evalバージョンだと(1)が返ってきてしまいます。その理由を考えてみると、p2の内部でpがdefineされた後、pが作用されますが、このときpの仮パラメータであるeに(set! x (cons x '(2)))がdelay-itされた上で束縛されます。その後、pの本体であるe->xという順に評価されるわけですが、この時それぞれの式はactual-valueではなく、ただのevalが実行されます。evalにeが渡されると、eは式ではなくvariableなので、束縛されている値をlookupするだけで終わってしまいます。つまり、束縛されているset!が評価される機会が発生しません。その結果、次のxが評価されて、xの束縛値である1が返ることになります。actual-valueを使っていれば、lookupされたeの束縛値に対してforce-itされるので、set!が評価され、xは(1 2)に更新されます。
cについては、eval-sequenceでactual-valueを使っても、force-itはthunkタグがなければそのまま渡された値を返すだけなので、遅延オブジェクトでなければevalと動きは変わらないのではと思います。
dの考察と、問題4-31は飛ばしました。