有人可以向我解释"卫生"的概念(我是计划程序员)吗?

Cam*_*Cam 28 macros scheme hygiene r6rs

所以...我是计划r6rs的新手,我正在学习宏.有人可以向我解释"卫生"是什么意思吗?

提前致谢.

nam*_*min 24

卫生通常用于宏的上下文中.卫生宏不使用可能存在干扰扩展代码的变量名称.这是一个例子.假设我们想or用宏定义特殊形式.直观地说,

(or a b c ... d)会扩展到类似的东西(let ((tmp a)) (if tmp a (or b c ... d))).((or)为简单起见,我省略了空案例.)

现在,如果名称tmp实际上是在代码中添加的,就像在上面描绘的扩展中一样,它将不卫生,而且很糟糕,因为它可能会干扰另一个具有相同名称的变量.说,我们想评估

(let ((tmp 1)) (or #f tmp))
Run Code Online (Sandbox Code Playgroud)

使用我们的直观扩展,这将成为

(let ((tmp 1)) (let ((tmp #f)) (if tmp (or tmp)))
Run Code Online (Sandbox Code Playgroud)

tmp从宏阴影最外面的tmp,所以结果是#f代替1.

现在,如果宏是卫生的(并且在Scheme中,它在使用时会自动出现syntax-rules),那么tmp您将使用保证不会出现在代码中其他任何位置的符号,而不是使用扩展名称.您可以gensym在Common Lisp中使用.

Paul Graham的On Lisp在宏上提供了高级材料.


Jör*_*tag 8

如果你想象一个宏被简单地扩展到它被使用的地方,那么你也可以想像,如果你使用一个变量a在您的宏,有可能已经一个变量a,在其中使用了宏定义的地方.

这是不是a你想要的!

一个像这样的事情不可能发生的宏观系统被称为卫生.

有几种方法可以解决这个问题.一种方法是在宏中使用非常长,非常神秘,非常难以预测的变量名称.

一个稍微更精致的版本是gensym一些其他宏系统使用的方法:代替,程序员提出一个非常长,非常神秘,非常难以预测的变量名称,你可以调用gensym生成一个非常长,非常非常长的函数为您提供神秘,非常不可预测且唯一的变量名称.

就像我说的那样,在一个卫生的宏观系统中,这种碰撞一开始就不会发生.如何使宏观系统卫生本身就是一个有趣的问题,计划社区已经花了几十年时间研究这个问题,并且他们不断提出更好,更好的方法.

  • *挥手*这些不是你正在寻找的. (3认同)
  • 这有几个错误的部分:(a)在宏中使用长而神秘的名称*不是解决方案,它只是一种延迟宏的方法 - 特别是,当宏在自身内部使用时,它可能会以明显的方式失败.(b)你只提到问题的一个方面,即绅士解决的问题; 另一方面是宏定义中的绑定不能被其使用中的绑定所遮蔽,例如:`(let((if"bleh"))(my-macro))`.只有gensyms才能解决这个问题. (3认同)