我正在尝试解决计算机编程的结构和解释问题 4.4 的最后一部分;任务是实现或作为句法转换。只定义了基本句法形式;引用、if、begin、cond、define、apply 和 lambda。
(或 ab ... c) 等于第一个真值,如果没有值为真,则为假。
我想要处理的方法是将例如(或 abc)转换为
(if a a (if b b (if c c false)))
这样做的问题是 a、b 和 c 将被评估两次,如果其中任何一个有副作用,这可能会给出不正确的结果。所以我想要一个像让
(let ((syma a))
(if syma syma (let ((symb b))
(if symb symb (let ((symc c))
(if (symc symc false)) )) )) )
这又可以通过 lambda 实现,如练习 4.6 中所示。现在的问题是确定符号 syma、symb 和 symc;例如,如果表达式 b 包含对变量 syma 的引用,那么 let 将破坏绑定。因此,我们必须认为 sema 是不在 b 或 c 中的符号。
现在我们遇到了障碍;我能从这个洞中看到的唯一方法是让符号不能在传递给 eval 的任何表达式中出现。(这包括可能由其他句法转换传入的符号)。
但是,由于我无法直接访问表达式中的环境,因此我不确定是否有任何合理的方法可以生成此类符号;我认为 Common Lisp 为此目的具有 gensym 功能(这意味着元循环解释器中的粘滞状态,危及任何并发使用)。
我错过了什么吗?有没有办法实现或不使用 gensym?我知道 Scheme 有它自己的 hygenic 宏系统,但我还没有弄清楚它是如何工作的,我不确定它下面是否有一个 gensym。