In addition to Matthias answer:
You can also use set
T1> (defparameter *symbol* 'foo) *SYMBOL* T1> (set *symbol* 100) 100
since (set symbol value) == (setf (symbol-value symbol) value) , that is, unlike setq and setf , set evaluates its first argument. ( setq can be read as "set quoted") set is deprecated in Hyperspec, but since I do not expect the next CL standard in the near future, it should be used safely.
Also, I don’t think you will have to use symbol-value or any special ads to provide access to them in different ways - at least for all practical purposes. (Although it can be argued that technically, since you cannot rely on a modified symbol, even being locally special, the variable may not be evaluated using symbol-value , but see Naggum's referenced post below and Mattias's last sentence.)
It is true that setq , setf , set et al. only binding changes are guaranteed to match implementations. When used at the pool level, symbol-value will be changed, but you cannot rely on any global special declaration (or anything else) (see Naggum ). But typically, implementations will at least evaluate the new variable using the symbol-value slot. This does not mean that to access symbol-value you need to use special symbol-value declarations or local / global, but this means that a new binding of the same symbol will not be automatically special, as it will take place with variables entered through defparameter and friends.
So, although usually with global special variables:
T1> (let ((*symbol* 'bar)) (symbol-value '*symbol*)) BAR
A new non-global special binding will not be by itself:
T1> (let ((foo 101)) ; this new binding is lexical (symbol-value 'foo)) ; so symbol-value refers to the outer special 100 T1> (let ((foo 101)) foo) ; evaluation of foo new lexical binding 101 ; doesn't look at the `symbol-value`. lexical ; bindings are mere addresses at runtime.
And this is also where the local special declaration can be used to refer to the external (not global) special binding foo :
T1> (let ((foo 101)) foo) ; our new lexical binding 101 T1> (let ((foo 101)) (locally (declare (special foo)) foo)) ; the outer special binding 100 T1> (let ((foo 101)) (setq foo 102) ; modify the new lexical binding foo) 102 T1> foo ; doesn't modify the outer special binding 100 T1> (let ((foo 101)) (locally (declare (special foo)) (setq foo 102) ; modify the outer special binding foo)) 102 T1> foo 102
As far as I understand, the undefined part, or at least the one in which you should expect portability problems, is whether such top-level modifications can declare something (globally) special or not. The behavior I expect is what I showed here, but if the variable is declared globally special or not (or maybe even introduce a lexical toplevel variable?), If at least it is made locally special, you don’t you will need local declarations or symbol-value to access it.
In addition, you should consider whether you really need what you asked for. It is likely that what you want to do can be resolved in a more idiomatic (at least for modern Lispers) way, and relying on undefined behavior will not be considered a good style by most for anything other than using REPL.