Defparameter操作

时间:2016-10-31 19:01:22

标签: common-lisp

关于defparameter的操作 - 看起来它只会影响参数的符号值单元格:

> (defparameter *p* 16)
*P*

> (symbol-plist '*p*)
NIL

> (setf (symbol-plist '*p*) '(prop1 val1 prop2 val2))
(PROP1 VAL1 PROP2 VAL2)

> (defparameter *p* 16)
*P*

> (symbol-plist '*p*)
(PROP1 VAL1 PROP2 VAL2)

因此plist尚未重置为零。与symbol-function单元格等相同的操作。这看起来相当尴尬,因为重新加载/编译带有defparameter的文件会使先前的设置保持不变。有没有方便的方法一次重置所有内容?

2 个答案:

答案 0 :(得分:3)

是的,您可以通过unintern符号完全重置所有内容:

[1]> (defparameter foo 10)
FOO
[2]> (defun foo (x) (1+ x))
FOO
[3]> (setf (get 'foo 'x) 'y)
Y
[4]> (symbol-plist 'foo)
(X Y SYSTEM::DEFINITION
 ((DEFUN FOO (X) (1+ X)) . #(NIL NIL NIL NIL ((DECLARATION OPTIMIZE DECLARATION)))))
[5]> (setq old-foo 'foo)
FOO
[6]> (unintern 'foo)
T

现在这个符号是未加工的,当我们用read重新创建它时,它有一个“干净的石板”:

[7]> (fboundp 'foo)
NIL
[8]> (boundp 'foo)
NIL

但我们仍然可以通过old-foo访问其广告位:

[9]> old-foo
#:FOO
[10]> (fdefinition old-foo)
#<FUNCTION #:FOO (X) (DECLARE (SYSTEM::IN-DEFUN #:FOO)) (BLOCK #:FOO (1+ X))>

PS。正如Barry在评论中提到的那样,这可能会产生意想不到的后果,应谨慎使用。 具体来说,这是一种很好的方法,同时积极开发代码。 但是,在生产中不应该进行这种“清理”操作。

答案 1 :(得分:1)

要添加到sds告诉你的内容,如果你unintern一个符号并引入一个具有相同名称的新符号,那么你需要重建所有引用未分隔符号的代码,以便它可以引用新的一个。这就是为什么在生产代码中使用是不切实际的,因为重复编译一遍又一遍可能不是一个好主意。

  

有没有方便的方法一次性重置所有内容?

只需定义一个功能并在适当时重置您需要的内容: 或者,如果您希望在致电defparameter后仅发生一次,您也可以这样做。 请注意,我建议仅清除您控制的plist的属性,而不是删除其所有内容。环境可能会存储一些有用的东西,比如调试信息。

(defparameter *p* 16)

(eval-when (:compile-time :load-time :execute)
  (dolist (property '(prop-a prop-b prop-c))
    (setf (get '*p* property) nil)))

编辑:

我忘记了REMF

(remf (symbol-plist '*p*) 'property)

上面删除了条目,而(setf (get ...) nil)将指标绑定到NIL。