コンピュータープログラミングの構造と解釈の質問 4.4 の最後の部分を解こうとしています。タスクは、または構文変換として実装することです。基本的な構文形式のみが定義されています。quote、if、begin、cond、define、apply、およびラムダ。
(または ab ... c) は最初の真の値と等しいか、真の値がない場合は偽です。
私がそれにアプローチしたい方法は、たとえば(またはabc)を次のように変換することです
(if a a (if b b (if c c false)))
これの問題は、a、b、および c が 2 回評価されることであり、それらのいずれかに副作用があると、誤った結果が生じる可能性があります。だから私はレットのようなものが欲しい
(let ((syma a))
(if syma syma (let ((symb b))
(if symb symb (let ((symc c))
(if (symc symc false)) )) )) )
これは、演習 4.6 のようにラムダを介して実装できます。ここでの問題は、シンボル syma、symb、および symc を決定することです。たとえば、式 b に変数 syma への参照が含まれている場合、let はバインディングを破棄します。したがって、syma は b にも c にもない記号である必要があります。
ここで問題が発生しました。この穴から抜け出す唯一の方法は、eval に渡されたどの式にも含まれていないシンボルを持つことです。(これには、他の構文変換によって渡された可能性のあるシンボルが含まれます)。
ただし、式で環境に直接アクセスできないため、そのようなシンボルを生成する合理的な方法があるかどうかはわかりません。Common Lisp には、この目的のための関数 gensym があると思います (これは、メタサーキュラー インタープリターで状態を保持し、同時使用を危険にさらすことを意味します)。
何か不足していますか?gensym を使用せずに実装する方法はありますか? 私は、Scheme が独自のハイジェニック マクロ システムを持っていることを知っていますが、それがどのように機能するかを理解していません。また、下に gensym があるかどうかもわかりません。