提问人:eonil 提问时间:8/15/2010 最后编辑:Brian Tompsett - 汤莱恩eonil 更新时间:11/16/2023 访问量:5457
如何在Scheme中取消定义变量?
How to undefine a variable in Scheme?
答:
不能在标准 Scheme 中取消绑定变量。你可以设置!变量设置为“未定义”,我猜,或者你可以写一个元解释器来重新定义环境,允许你引入你自己的未定义变量的概念。
在 Scheme 中,变量是用 lambda 或各种 let 之一定义的。如果您希望其中一个是“未定义”的,那么您需要做的就是离开它们所在的范围。当然,这并不是真的取消定义它们,只是变量不再绑定到它以前的定义。
如果你使用(define)进行顶级定义,那么从技术上讲,你正在定义一个函数。由于 Scheme 是函数式的,因此函数永远不会真正消失。我想从技术上讲,它存储在某个地方的某种环境函数中,所以如果你非常熟悉你的实现(并且它没有以某种方式受到保护),你可能会用你自己对 globabl 环境的定义覆盖它。除此之外,我想说你最好的选择是重新定义函数以返回空列表——这真的是空的。
评论
display
(set! no-longer-needed #f)
这是否达到了您想要的效果?您还可以在顶层使用定义。
guile> (define nigel "lead guitar")
guile> nigel
"lead guitar"
guile> (define nigel #f)
guile> nigel
#f
guile>
然后,您可以重新设置变量。当然,这完全取决于变量的范围:参见 Greg 的回答。define
评论
我认为,如果你的观点是做相当于“免费”或取消分配的事情,那么不,你几乎不走运。您无法取消分配变量。你可以把它重新定义为一些小的东西,比如 #f,但是一旦你完成了(定义 foo 'bar),变量 foo 将以某种形式存在,直到你结束程序。
另一方面,如果你使用 let 或 letrec,当然,这个名字只存在到相关的关闭括号......
评论
你在这里触动了神经。Scheme 对顶级环境的工作方式没有非常明确的标准概念。为什么?因为 Scheme 标准代表了两组人之间的妥协,他们对 Scheme 应该如何运作有着截然不同的想法:
- 解释性人群,他们看到您上面描述的顶级环境:一个运行时哈希表,随着程序解释的进行,绑定会逐步添加。
- 然后是编译人群,他们认为顶级环境在编译时必须是完全可计算的(即,编译器必须能够最终识别将在顶级环境中绑定的所有名称)。
您的“如何取消定义变量”问题仅在第一个模型中才有意义。
请注意,解释模型(其中程序的顶级绑定取决于所采用的代码路径)使得 Scheme 代码的高效编译变得更加困难,原因有很多。例如,如果过程的名称是一个顶级绑定,它不仅可能在运行时发生变化,甚至可能消失在虚无中,那么 Scheme 编译器如何内联过程调用?
我坚定地站在编译阵营中,所以我建议你避免编写依赖于在运行时添加或删除顶级绑定的能力的代码,或者甚至需要使用顶级变量的代码(尽管这些通常是不可避免的)。一些 Scheme 系统(例如,Racket)能够生成相当好的编译代码,但如果你做出这些假设,你会在这方面绊倒它们。
评论
define
let
我认为你的问题并不愚蠢。在AutoLISP中,具有不存在的(未定义的)变量先验支持值“nil”(即使该变量在内存中不存在 - 这意味着 - 如果它不在变量表中 - 则该值为“nil” - “false”)。这也意味着错误。而且它也是空列表。如果你编写某种列表处理函数,只需通过以下方式进行初始测试就足够了:
(if input-list ....)
当您想要显式取消定义任何变量时,您可以这样做:
(setq old-var nil); or: (setq old-var ())
我喜欢。关键字“setq”的意思是“定义”。其他方言中的有界变量和无界变量哪个更好?你必须测试它们是否存在,如果它们是列表,你需要垃圾收集器,你不能取消定义变量来显式释放内存。如果未定义变量“my-list”,则无法编写以下命令:
(define my-list (cons 2 my-list))
因此,我认为 AutoLISP 方法更适合编程。我写的可能性,你可以在那里使用。遗憾的是,AutoLISP 只能在某些 CAD 工程图形系统中工作。
评论
nil
undefined
如其他答案所述,在 Scheme 中没有操作命名空间的标准方法。对于特定的实现,可能有一个解决方案。
在 Racket 中,顶级变量存储在命名空间中。您可以使用 删除变量。namespace-undefined-variable
无法删除局部变量。
方案 (R7RS) 没有符合标准的方法来删除顶级绑定。
如果计算不存在的变量,则会出现错误:
(eval 'a)
; => ERROR: undefined variable: a
如果定义它,则该变量将添加到顶级环境中。
(define a 1)
(eval 'a)
; => 1
从现在开始,无论你做什么,如果你访问变量,你都不会得到错误。
如果将其设置为 false,则将得到 false:
(set! a #f)
(eval 'a)
; => #f
即使将其设置为未指定的内容,也不太可能出现错误:
(set! a (if #f #t))
(eval 'a)
; =>
但是,某些方案可能具有删除顶级绑定的非标准方法。MIT Scheme 提供了 unbind-variable
函数。
评论