How to undo a `declaration` proclamation?
Asked Answered
G

1

7

It appears that most (if not all) global declarations cannot be reverted in an ANSI CL standard way.

E.g., once you evaluate (either directly or by loading a file) a form like (proclaim '(declaration my-decl)) or (declaim (special *my-var*)) there is no portable way to make (declare (my-decl ...)) illegal or *my-var* lexical.

Various implementation offer non-portable way to revert the special declaration, usually via (proclaim '(notspecial *my-var*)) or some other trick.

How about the declaration proclamation?

How do various implementations undo it? How would you implement it? Do you think (proclaim '(notdeclaration my-decl)) is a good idea?

Motivation: in a test suite, it would be nice to be modular - to be able to revert all effects of a test statements to avoid any possible interference with test suite parts. I know it's a week motivation because The Right Way is to use packages.

Gratuity answered 3/8, 2017 at 14:55 Comment(2)
Hmm. What happens if you unintern the symbol for the variable? This would probably be a bad idea as it will mess up any boundary between old/new references to the symbolGamp
I don't see any proper way to do it in SBCL, but it seems like (setf (sb-int:info :declaration :recognized name-of-the-declaration) nil) would do it.Forevermore
H
1

One possible way is to provide a transaction mechanism (rollback/commit). This is taken from Xach's Naggum's archive:

I miss a transaction facility where I can make a number of changes
to the system that are only visible to my thread of a multi-threaded
execution environment and then discard them or commit them all at
once. E.g., loading a file could be such a transcation. Signaling
an error during loading could cause the whole slew of operations
that preceded it to be discarded instead of leaving the system in a
partially modified state. This is not impossible to build on top of
the existing system, but it takes significant effort, so it is the
kind of thing that Common Lisp systems programmers should do.

You would miss the possibility to undo only a subset of the declarations, like (declare A), (declare B), (undeclare A) but given your motivation, it would not be a problem because you are likely to want to undo all possible declarations made during a test.

You could provide a special form to individually "undeclare" declarations. I'd name it retract, but this might be difficult to specify in some cases. Suppose you declare that x is either a string or a number, can you retract a declaration that says x is a string? What about inline functions, etc? A transaction looks easier to implement, with e.g. a temporary environment.

Husch answered 4/8, 2017 at 9:55 Comment(2)
I was asking about a syntax that would exposed the mechanism, but the transaction approach is, indeed, interesting.Gratuity
@Gratuity For the syntax, I would rather have (declaim (not X)) with X any valid declaration expression than different notdeclaration symbol for each valid declaration. Also, not might be confusing: (declare (not (type T X))) is generally not the same as (declare (type (not T) X)). Prolog has assert and retract built-ins, maybe (retract declaration) would be better.Husch

© 2022 - 2024 — McMap. All rights reserved.