你在这里感动神经.Scheme没有关于顶级环境如何工作的非常明确的标准概念.为什么?因为Scheme标准代表了两组人之间的妥协,他们对Scheme应该如何工作的想法截然不同:
您的"我如何取消定义变量"问题仅在第一个模型中有意义.
请注意,解释模型(程序的顶级绑定取决于所采用的代码路径)使得有效编译Scheme代码变得更加困难,原因很多.例如,如果过程的名称是顶级绑定,并且可能不仅在运行时更改,甚至消失为虚无,那么Scheme编译器如何内联过程调用?
我坚定地在这里的编译阵营,所以我建议你避免编写依赖于在运行时添加或删除顶级绑定的代码,或者甚至需要使用顶级变量(虽然这些通常是不可避免的).一些Scheme系统(例如,Racket)能够产生相当好的编译代码,但是如果你做出这些假设,你就会在这方面绊倒它们.
小智 5
在Scheme中,变量用lambda或各种let之一定义.如果你想让其中一个被"未定义",那么你需要做的只是留下它们所在的范围.当然,这并不是真正取消它们,只是变量不再绑定到它之前的定义.
如果您使用(define)进行顶级定义,那么从技术上讲,您将定义一个函数.由于Scheme功能正常,功能永远不会消失.我认为从技术上讲,它存储在某种环境函数中,所以如果你非常熟悉你的实现(并且它不以某种方式得到保护),你可能会用你自己的globabl环境定义来覆盖它.除此之外,我会说你最好的选择是重新定义函数以返回空列表 - 这真的是空的.
Scheme ( R7RS ) 没有标准兼容的方法来删除顶级绑定。
如果您评估一个不存在的变量,则会出现错误:
(eval 'a)
; => ERROR: undefined variable: a
Run Code Online (Sandbox Code Playgroud)
如果您定义它,该变量将被添加到顶级环境中。
(define a 1)
(eval 'a)
; => 1
Run Code Online (Sandbox Code Playgroud)
从现在开始,无论您做什么,如果您访问该变量,都不会出错。
如果将其设置为 false,则会得到 false:
(set! a #f)
(eval 'a)
; => #f
Run Code Online (Sandbox Code Playgroud)
即使您将其设置为未指定的内容,也不太可能出现错误:
(set! a (if #f #t))
(eval 'a)
; =>
Run Code Online (Sandbox Code Playgroud)
但是Schemes 可能有一种非标准的方法来删除顶级绑定。MIT Scheme 提供了这个功能unbind-variable。