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

时间:2014-01-20 10:40:48

标签: lisp elisp common-lisp

在Python中,我们有del语句来删除变量。

E.g:

a = 1
del a

在Lisp中这相当于什么?

(setq foo 1)
;; (del foo) ?

4 个答案:

答案 0 :(得分:23)

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(已定义)
  • SLOT-MAKUNBOUND(已定义)
  • FMAKUNBOUND(已定义)

答案 1 :(得分:8)

Python名称驻留在名称空间中,del从名称空间中删除名称。 Common Lisp有不同的设计,对编译高效代码更加同情。

在常见的lisp中,我们有两种“变量”。词汇变量占其中的大多数。词汇变量类似于C local。在运行时,词法变量通常被实现为一点存储(在堆栈上)并且仅保留与其名称的关联以用于调试目的。在python使用的意义上谈论删除词法变量并没有任何意义,因为与词汇变量存在的python命名空间最接近的类比是词法范围,而纯粹是规范和编译器/评估者使用的抽象

CL中的第二个变量类型“变量”是“全局”符号。符号是非常丰富的数据结构,比python中的标签更丰富。它们可以包含大量与它们相关的信息,值,打印名称,“主页”包,函数以及存储在属性列表中的其他任意信息。其中大多数是可选的。在源代码中使用名称时,例如(+ X 3),名称X通常表示词汇符号。但是,如果编译器/评估者认为你不想要“全局”符号的值,那就失败了。即你有效地写了(符号 - 值'X)而不是X.由于几十年前的拼写错误,编程惯例和其他事情,编译器开始抱怨在没有声明符号是的符号的情况下引用“全局”符号意图是“全球化”。该声明被称为“特殊”。是的,这是一个愚蠢的命名法。更糟糕的是,特殊变量不仅仅是全局变量,它们还有一个非常有用的功能,称为动态绑定 - 但这是另一个主题。

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

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

您可以从包中删除符号(请参阅unintern)。但这是一种罕见的事情,可能会让你的大脑受到伤害。这是一个简单的操作,但它的边缘令人困惑,因为包装系统有一小部分聪明的功能,虽然非常有帮助,但需要花费一点力气才能舒服。因此,从某种意义上说,对你的问题的简短回答是,对于全局符号,unintern是类似的操作。但是,如果您使用它,可能会做一些非常特殊的事情(可能是错误的)。

答案 2 :(得分:4)

虽然@Ben写的是真的,但我猜你所要找的是 makunbound ,而不是unintern。前者不会从obarray(对于Emacs Lisp)或包(对于Common Lisp)中删除符号。它只删除了symbol-value,即 值作为变量 。如果您希望尝试获取变量值的行为导致无约束(也称为无效)错误,请尝试makunbound

答案 3 :(得分:0)

我并不反驳以前的答案,而是补充说明。

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

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

其他答案基本上告诉你Lisp没有提供摆脱 abc 的方法。您可以使用 makunbound ,以便符号是新鲜的,没有赋值。并且您可以使用 unintern 使符号不在任何包中。然而 boundp 会告诉您符号仍然存在。

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

真正摆脱 abc 的另一种方法是关闭Lisp并重新启动它。看起来不太可取。但我认为关闭Lisp并开始新鲜是实际摆脱所有符号。然后定义所需的符号。

您可能通常需要 makunbound ,因为如果您尝试将 abc 的值添加到其他地方,系统将发出错误信号,因为 abc 没有任何价值。如果您尝试将 abc 附加到字符串,系统将发出错误信号,因为 abc 没有字符串。等