如何在Scheme中取消定义变量?这可能吗?
答案 0 :(得分:6)
你在这里感动神经。 Scheme没有关于顶级环境如何工作的非常明确的标准概念。为什么?因为Scheme标准代表了两组人之间的妥协,他们对Scheme应如何运作有着截然不同的想法:
您的“我如何取消定义变量”问题仅在第一个模型中有意义。
请注意,解释模型(程序的顶级绑定取决于所采用的代码路径)使得有效编译Scheme代码变得更加困难,原因很多。例如,如果过程的名称是顶级绑定,并且可能不仅仅在运行时更改,甚至消失为虚无,那么Scheme编译器如何内联过程调用?
我坚定地参与编译阵营,所以我建议你避免编写依赖于在运行时添加或删除顶级绑定的代码,或者甚至需要使用top-等级变量(尽管这些变量通常是不可避免的)。一些Scheme系统(例如,Racket)能够产生相当好的编译代码,但如果你做出这些假设,你就会在这方面绊倒它们。
答案 1 :(得分:5)
在Scheme中,变量是使用lambda或其中一个let来定义的。如果你想让其中一个被“未定义”,那么你需要做的只是留下它们所在的范围。当然,这并不是真正取消它们,只是变量不再绑定到它之前的定义。
如果您正在使用(define)制作顶级定义,那么从技术上讲,您将定义一个函数。由于Scheme功能正常,功能永远不会消失。我认为从技术上讲,它存储在某种环境函数中,所以如果你非常熟悉你的实现(并且它不以某种方式得到保护),你可能会用你自己的globabl环境定义来覆盖它。除此之外,我会说你最好的选择是重新定义函数以返回空列表 - 这真的是空的。
答案 2 :(得分:3)
(set! no-longer-needed #f)
这是否达到了你想要的效果?您也可以在顶层使用define。
guile> (define nigel "lead guitar")
guile> nigel
"lead guitar"
guile> (define nigel #f)
guile> nigel
#f
guile>
然后你可以重新define
变量。这一切都取决于变量的范围,当然:见Greg's answer。
答案 3 :(得分:3)
Scheme(R7RS)没有符合标准的方法来删除顶级绑定。
如果您评估一个非现有变量,则会收到错误:
(eval 'a)
; => ERROR: undefined variable: a
如果您定义它,变量将被添加到顶级环境中。
(define a 1)
(eval 'a)
; => 1
从现在开始,无论你做什么,如果访问变量,都不会出错。
如果将其设置为false,则会出现错误:
(set! a #f)
(eval 'a)
; => #f
即使您将其设置为未指定的内容,也不太可能出现错误:
(set! a (if #f #t))
(eval 'a)
; =>
但方案可能采用非标准方式删除顶级绑定。 MIT Scheme提供函数unbind-variable
。
答案 4 :(得分:1)
您无法在标准Scheme中取消绑定变量。你可以设置!变量为'undefined,我猜,或者你可以编写一个metainterpreter来统一环境,允许你介绍你自己的定义变量的概念。
答案 5 :(得分:1)
我认为,如果你的观点是相当于“免费”或取消分配,那么你就不会有运气了。你无法取消分配变量。你 CAN 将它重新定义为小的东西,比如#f,但是一旦你完成了(定义foo'bar),变量foo将以某种形式存在,直到你结束程序。
另一方面,如果你使用let或者letrec,当然这个名字只存在于相关的关闭之前......
答案 6 :(得分:1)
如其他答案中所述,没有标准的方法来操作Scheme中的命名空间。对于特定实现,可能存在解决方案。
在Racket中,顶级变量存储在命名空间中。您可以使用namespace-undefined-variable
删除变量。
无法删除局部变量。
答案 7 :(得分:0)
我认为你的问题不是愚蠢的。在AutoLISP中有未存在的(未定义的)变量apriori supposted值“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工程图形系统。