Post by James CloosKK> Ah, if you mean new symbols which evaluate to themselves,
KK> and are not the keywords or T or NIL?
KK> The obvious way is to just bind them as lexical variables
KK> (or perhaps globals) or macros.
KK> E.g.
KK> (define-symbol-macro foo 'foo)
KK> Now when foo is evaluated, it goes to (quote foo) which goes to foo.
cool intel. i hadn’t though of define-symbol-macro.
Fun fact: in the original LISP, the symbol T was implemented
as a binding of the T variable to the value T. Only NIL was
genuinely self-evaluating (iirc). This T was just a convention; as in,
the system provided this T variable to be used as canonical
representation of truth rather than just any non-NIL value.
I see other answers in this thread have resorted to defconstant. It
seems reasonable in this case. I don't like resorting to it because the
spec says that it defines a constant variable, which is a ridiculous
oxymoron to me: variable and constants are literally opposites,
according to any major English language dictionary.
What defconstant does is promise to the compiler that the variable will
not change. Therefore the compiler can go to town with
constant-propagating the value. This isn't a problem in this case.
When you use defconstant, the timing of the evaluation of the form isn't
precise. A compiler could evaluate it at compile time, for the purpose
of the aforementioned constant propagation. Or it could be delayed to
the time when the code is loaded (while still treated aggressively as a
constant in other regards, like loaded into a register, and then assumed
to be valid even across external function calls.) Not a problem in
this case either: we have an obvious constant.
defconstant is riddled with undefined consequences.
- Another defcosntant for the same symbol must have a value which is eql
to the original one.
- Assigning to a defconstant is undefined.
- The application binds a defconstant symbol as a lexical or
dynamic variable.
Even though implementations can diagnose situatons like that, the
undefinedness is a turn-off.
It's not clear whether makunbound is required to remove a defconstant,
which can then be redefined as an ordinary dynamic or lexical variable,
or a defconstant with a different value. Given all the admonishments in
the specification of defconstant, it is hard to find assurance in the
absence of any mention of defconstant under makunbound.
defconstant was clearly introduced as an optimization mechanism, and its
design is in keeping with that, similarly to (declare (optimize ..)) and
all that, where you make some promises to the compiler with consequences
if you break them.
Thus, I instnictively reached for define-symbo-macro. I know when
that will be expanded and what it will do:
- define-symbol-macro's spec mentions udefined consequences only once.
- the macro may be safely shadowed by a lexical.
- If the symbol is already defined as a global variable, this is an
error situation requiring a signal.
- you can assign to a symbol macro if it expands to a form that is
an assignable place (not applicable when it expands to a quoted
symbol, obviously).
- there is a lexical form for symbol macros: symbol-macrolet.
defconstant has no local form.
It's still unclear (or I would say even less clear) whether makunbound
removes a global symbol macro.
My analysis leads to be regard symbol macros bound to constant
expressions as the true constant mechanism in Common Lisp, whereas
defconstant is just a compiler jig for speed demons and daredevils
looking to optimize their programs.
The only advantage of defconstant is that it turns any expression into
its value, after which the binding is regarded as cosntant. So if
we wanted A to evaluate to itself, we could use not only
(defcosntant a 'a) but also (defconstant a (cadr '(x a y)))
This is quite necessary when constants are the result of complex math
formuls, including function calls. It's a boon to numeric code.
defconstant is the grand uncle of newly emerging mechanisms in blub
languages, like constexpr in C++. However, those mechanisms are
cleaner and have some things in common with symbol macros,
like the ability to have lexical contexprs that cleanly shadow.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca