使用Common Lisp。
对于符号作为变量:
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.
参见:
makunbound
操作并不能防止它与同名的词法变量产生干扰 - 这是坚持使用 *earmuffs*
约定的另一个原因,这样您就永远不会有相同名称的词法变量和动态变量。 - Mark ReedPython的名称存储在命名空间中,del从命名空间中删除名称。Common Lisp具有不同的设计,更加有利于编译高效的代码。
在Common Lisp中,我们有两种“变量”类型。大多数情况下,词法变量占据了这些变量。词法变量类似于C语言中的局部变量。在运行时,词法变量通常被实现为一小段存储(例如栈)并且与其名称的关联仅保留用于调试目的。使用Python的名称空间存在最接近词法变量的类比是词法作用域,而这只是规范、编译器和求值器使用的抽象概念。
CL中第二个“变量”类型的“变量”是“全局”符号。符号是非常丰富的数据结构,比Python中的标签要丰富得多。它们可以具有许多信息,如值、打印名称、它们的“home”包、函数以及存储在属性列表中的其他任意信息。其中大多数是可选的。当您在源代码中使用名称时,例如(+ X 3),该名称X通常表示一个词法符号。但如果没有失败,编译器/求值器将假设您想要“全局”符号的值。也就是说,您实际上编写了(symbol-value'X),而不是X。由于打字错误、编程惯例和其他一些原因,几十年前的编译器开始抱怨在没有指示符号旨在成为“全局”符号的声明的情况下对“全局”符号的引用。这个声明被称为“special”。是的,这是一个愚蠢的命名约定。更糟糕的是,特殊变量不仅是全局的,它们还具有一个非常有用的功能,称为动态绑定——但这是另一个话题。
几乎总是使用defvar、defparameter或defconstant声明特殊的符号。有一个几乎强制性的编码约定,即它们要唯一拼写,例如*X*而不是X。一些编译器以及大多数开发人员将抱怨您违反该约定。
好的。现在我们可以回到del。特殊变量用符号表示;这类似于python中使用名称表示变量。在python中,名称在当前命名空间中查找。在Common Lisp中,它们在当前包中查找。但查找发生的时间不同。在python中,它在运行时完成,因为名称可以动态添加和删除。在Common Lisp中,名称在编译程序之前从文件中读取时进行查找。(有一些例外,但让我们避免考虑这些。)
您可以从包中删除符号(请参见unintern)。但这是一件罕见的事情,可能只会让您头疼。这是一个简单的操作,但在边缘处会变得混乱,因为包系统具有一些聪明的功能,虽然非常有帮助,但需要花费一些精力才能熟悉。因此,在某种意义上,对于全局符号,unintern是类似的操作。但如果您正在使用它,那么您可能正在做一些非常特殊的事情(并且很可能是错误的)。
makunbound
,而不是unintern
。对于Emacs Lisp,前者不会从obarray中删除符号,对于Common Lisp,则不会从包中删除。它只是删除其symbol-value
,也就是其作为变量的值。如果您想要尝试获取变量值时出现未绑定(又称为空)错误的行为,则请尝试makunbound
。
set!
,更别说makunbound
了。" - Will Ness