如何在Lisp中删除变量/表单?

如何在Lisp中删除变量/表单?,lisp,elisp,common-lisp,Lisp,Elisp,Common Lisp,在Python中,我们有删除变量的语句 例如: 这在Lisp中的等价物是什么 (setq foo 1) ;; (del foo) ? 用通俗的口齿不清 对于作为变量的符号: CL-USER 7 > (setf foo 42) 42 CL-USER 8 > foo 42 CL-USER 9 > (makunbound 'foo) FOO CL-USER 10 > foo Error: The variable FOO is unbound. 见: 未绑定(已

在Python中,我们有删除变量的语句

例如:

这在Lisp中的等价物是什么

(setq foo 1)
;; (del foo) ?
用通俗的口齿不清

对于作为变量的符号:

CL-USER 7 > (setf foo 42)
42

CL-USER 8 > foo
42

CL-USER 9 > (makunbound 'foo)
FOO

CL-USER 10 > foo

Error: The variable FOO is unbound.
见:

  • 未绑定(已定义)
  • 插槽未绑定(已定义)
  • FMAKUNBOUND(已定义)

Python名称驻留在名称空间中,del从名称空间中删除名称。CommonLisp有一个不同的设计,一个更适合编译高效代码的设计

在CommonLisp中,我们有两种“变量”,其中大部分是词汇变量。词汇变量类似于C局部变量。在运行时,词法变量通常被实现为一个存储位(比如在堆栈上),并且与它的名称的关联仅保留用于调试目的。在python使用的意义上谈论删除词汇变量实际上没有任何意义,因为与词汇变量存在的python名称空间最相似的是词汇作用域,而这纯粹是规范和编译器/计算器使用的抽象

CL中的第二种变量类型“变量”是“全局”符号。符号是非常丰富的数据结构,比python中的标签丰富得多。它们可以有很多与它们相关的信息,一个值、一个打印的名称、它们的“主”包、一个函数,以及存储在属性列表中的其他任意信息。其中大多数是可选的。当您在源代码中使用名称时,例如(+x3),该名称X通常表示词汇符号。但如果失败,编译器/计算器将假定您需要“全局”符号的值。也就是说,您有效地编写了(符号值'X)而不是X。几十年前,由于打字错误、编程约定和其他原因,编译器开始抱怨在没有声明表示符号是“全局”的情况下引用了“全局”符号。该声明称为“特殊”是的,这是一个愚蠢的命名法。更糟糕的是,特殊变量不仅仅是全局变量,它们还有一个非常有用的特性,称为动态绑定,但这是另一个主题

特殊符号几乎总是使用defvar、defparameter或defconstant声明。有一种几乎是强制性的编码约定,即它们的拼写是唯一的,即.*X*而不是X。如果您偏离该约定,一些编译器和大多数开发人员会抱怨

嗯。所以现在我们可以回到戴尔。特殊变量用符号表示;这类似于python中用名称表示变量的方式。在python中,名称在当前名称空间中查找。在Common Lisp中,它们在当前包中查找。但查找发生的时间不同。在python中,这是在运行时完成的,因为名称可以在程序运行时动态添加和删除。在Common Lisp中,当程序在编译之前从文件中读取时,会查找名称。(也有例外,但我们不要去想这些。)


可以从包中删除符号(请参见Untrn)。但这是一件罕见的事情,可能只会让你的大脑受伤。这是一个简单的操作,但它得到的边缘混淆,因为包系统有一个小剂量的聪明的功能,虽然非常有帮助,需要一点努力,以变得舒适。所以,在某种意义上,你的问题的简短答案是,对于全局符号,untrn是类似的操作。但是如果你使用它,你可能会做一些非常特殊的事情(很可能是错误的)。

虽然@Ben写的是真的,但我猜你要找的是
makunbund
,而不是
untrn
。前者不会从obarray(对于Emacs Lisp)或包(对于Common Lisp)中删除符号。它只是删除它的
符号值
,即它的值作为变量。如果您希望尝试获取变量值会导致未绑定(也称为void)错误,请尝试
makunbund

我不是在反驳前面的答案,而是在添加

假设Lisp有垃圾收集。正如您所知,可以通过多种方式定义符号:setf、defvar、defparameter、make-symbol、以及许多其他方式

但是,如何获得一个干净的系统呢?如何确保不会错误地使用变量?例如,您定义了abc,然后决定不使用abc。相反,您需要abc-1和abc-2。如果您尝试使用abc,您希望Lisp系统发出错误信号。如果您无法以某种方式擦除abc,则系统不会通过发出“未定义”错误信号来阻止您

其他答案基本上告诉您Lisp并没有提供一种摆脱abc的方法。您可以使用makunbound,使符号保持新鲜,且不指定任何值。您可以使用untrn,使中的符号不在任何包中。然而,boundp将告诉您符号仍然存在

所以,我认为只要没有其他符号指向abc,垃圾收集最终就会摆脱abc。例如,(setfpt到abc)。只要pt to abc仍然绑定到符号abc,即使使用垃圾回收,abc也将继续存在

真正摆脱abc的另一种方法是关闭Lisp并重新启动它。看起来不太理想。但我认为,关闭口齿不清和重新开始实际上是摆脱所有符号的原因。然后定义所需的符号

您可能通常希望取消绑定,因为如果您尝试将abc的值添加到其他内容中,系统将发出错误信号,因为abc没有任何值。如果您试图将abc附加到字符串,系统将发出错误信号,因为abc没有字符串。诸如此类。

这看起来像是一场灾难。对这种模式的需求应该很少出现。
CL-USER 7 > (setf foo 42)
42

CL-USER 8 > foo
42

CL-USER 9 > (makunbound 'foo)
FOO

CL-USER 10 > foo

Error: The variable FOO is unbound.