davypough
davypough

Reputation: 1941

Defparameter operation

Concerning the operation of defparameter--it looks like it only affects the symbol-value cell of the parameter:

> (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)

so the plist has not been reset to nil. Same kind of operation with the symbol-function cell, etc. This seems rather awkward, since reloading/compiling a file with defparameters leaves the prior settings hanging around. Is there any convenient way to reset everything at once?

Upvotes: 1

Views: 344

Answers (2)

coredump
coredump

Reputation: 38789

To add to what sds told you, if you unintern a symbol and introduce a fresh symbol with the same name, then you need to rebuild all the code that referenced the uninterned symbol so that it can refer to the new one. That's why it is impractical to use in production code, where recompiling things over and over would probably not be a good idea.

Is there any convenient way to reset everything at once?

Just define a function and reset what you need to when appropriate: Or, if you want it to happen only once after you call defparameter, you can do it too. Note that I would recommend clearing only the properties of the plist you control instead of getting rid of all its content. The environment might store some useful stuff there, like debugging information.

(defparameter *p* 16)

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

Edit:

I forgot about REMF:

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

The above removes the entry, whereas (setf (get ...) nil) binds the indicator to NIL.

Upvotes: 1

sds
sds

Reputation: 60004

Yes, you can reset everything completely by uninterning the symbol:

[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

now the symbol is uninterned and when we re-create it with read, it has a "clean slate":

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

but we can still access its slots via old-foo:

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

PS. As Barry mentions in a comment, this might have unintended consequences and should be used with care. Specifically, this is a fine method while actively developing code. However, there should be no need for this "clean-up" operation in production.

Upvotes: 3

Related Questions