Discussion:
defining self-evaluating objects
(too old to reply)
James Cloos
2023-04-12 16:41:03 UTC
Permalink
does cl support defining new self-evaluating objects
(other than keywords)?

if so, how?

searching didn’t return any help.

i looked through the sbcl src to see how t is defined, but could not
find it. nor did i find the code responsible for keywords...

-JimC
--
James Cloos <***@jhcloos.com> OpenPGP: 0x997A9F17ED7DAEA6
Spiros Bousbouras
2023-04-12 17:41:36 UTC
Permalink
On Wed, 12 Apr 2023 12:41:03 -0400
Post by James Cloos
does cl support defining new self-evaluating objects
(other than keywords)?
Not that I know of but perhaps you can give some more information what
kind of thing you have in mind or what you're trying to achieve. Perhaps
reader macros would help.
Alan Bawden
2023-04-12 18:24:56 UTC
Permalink
James Cloos <***@jhcloos.com> writes:

does cl support defining new self-evaluating objects
(other than keywords)?

if so, how?

Anything that isn't a symbol or a cons is self-evaluating. So you can
just make new instances of any class or structure:

* (defstruct frob)
frob
* #S(frob)
#S(frob)

- Alan
Alan Bawden
2023-04-13 21:44:27 UTC
Permalink
James Cloos <***@jhcloos.com> writes:

does cl support defining new self-evaluating objects
(other than keywords)?

if so, how?

Here's another possibility:

* (defvar x #1='#1#)
x

The value of X is now a self-evaluating object. Here's proof:

* (eq x (eval x))
t

You might find the printed representation of the value of X to be a bit
inconvenient...

[I normally run with *PRINT-CIRCLE* set to NIL, because I find it
annoying in some situations, and I can rely on *PRINT-LEVEL* and
*PRINT-LENGTH* to keep printed representations under control. But in
SBCL 2.2.0 at least, that's not good enough to keep the above example
from blowing the stack when it tries to print the value of X, and only
setting *PRINT-CIRCLE* to T prevents that.]

- Alan
Jeff Barnett
2023-04-13 23:53:54 UTC
Permalink
Post by James Cloos
does cl support defining new self-evaluating objects
(other than keywords)?
if so, how?
* (defvar x #1='#1#)
x
* (eq x (eval x))
t
You might find the printed representation of the value of X to be a bit
inconvenient...
[I normally run with *PRINT-CIRCLE* set to NIL, because I find it
annoying in some situations, and I can rely on *PRINT-LEVEL* and
*PRINT-LENGTH* to keep printed representations under control. But in
SBCL 2.2.0 at least, that's not good enough to keep the above example
from blowing the stack when it tries to print the value of X, and only
setting *PRINT-CIRCLE* to T prevents that.]
I don't think your example above really works. If X is self evaluating
then (EQ X (QUOTE X)) should be T. And this requirement directly entails
that the reader must be involved to some degree.
--
Jeff Barnett
Alan Bawden
2023-04-14 04:26:23 UTC
Permalink
Post by Alan Bawden
* (defvar x #1='#1#)
x
* (eq x (eval x))
t
You might find the printed representation of the value of X to be a bit
inconvenient...
[I normally run with *PRINT-CIRCLE* set to NIL, because I find it
annoying in some situations, and I can rely on *PRINT-LEVEL* and
*PRINT-LENGTH* to keep printed representations under control. But in
SBCL 2.2.0 at least, that's not good enough to keep the above example
from blowing the stack when it tries to print the value of X, and only
setting *PRINT-CIRCLE* to T prevents that.]
I don't think your example above really works. If X is self evaluating then
(EQ X (QUOTE X)) should be T. And this requirement directly entails that
the reader must be involved to some degree.

This is exactly why I didn't claim that "X is now a self-evaluating
object". I explicity wrote that "THE VALUE OF X is now a
self-evaluating object". I knew that the OP was almost certainly
looking for something that he could easily type in repeatably, but he
only ASKED for something that was "self-evaluating", so I (perhaps
mischievously) chose to answer his literal question. And I don't know
what "self-evaluating" could possibly mean unless it is defined as:

(defun self-evaluating-p (x)
(eq x (eval x)))

- Alan
Madhu
2023-04-17 01:37:02 UTC
Permalink
Post by Alan Bawden
Post by Alan Bawden
* (defvar x #1='#1#)
x
* (eq x (eval x))
t
You might find the printed representation of the value of X to be a bit
inconvenient...
[I normally run with *PRINT-CIRCLE* set to NIL, because I find it
annoying in some situations, and I can rely on *PRINT-LEVEL* and
*PRINT-LENGTH* to keep printed representations under control. But in
SBCL 2.2.0 at least, that's not good enough to keep the above example
from blowing the stack when it tries to print the value of X, and only
setting *PRINT-CIRCLE* to T prevents that.]
I don't think your example above really works. If X is self evaluating then
(EQ X (QUOTE X)) should be T. And this requirement directly entails that
the reader must be involved to some degree.
This is exactly why I didn't claim that "X is now a self-evaluating
object". I explicity wrote that "THE VALUE OF X is now a
self-evaluating object". I knew that the OP was almost certainly
looking for something that he could easily type in repeatably, but he
only ASKED for something that was "self-evaluating", so I (perhaps
mischievously) chose to answer his literal question. And I don't know
(defun self-evaluating-p (x)
(eq x (eval x)))
http://www.lispworks.com/documentation/HyperSpec/Body/03_abac.htm

Certain specific symbols and conses might also happen to be
``self-evaluating'' but only as a special case of a more general
set of rules for the evaluation of symbols and conses; such
objects are not considered to be self-evaluating objects.

So Common Lisp really takes the fun out of quines, by explicitly
specifying that conses are not considered to be self-evaluating objects.

So the defvar example above, #1=(print '#1#),
((lambda(lambda)`(,lambda',lambda))'(lambda(lambda)`(,lambda',lambda)))
none of these count as self-evaluating objects according to the spec.
Alan Bawden
2023-04-17 05:27:29 UTC
Permalink
Madhu <***@meer.net> writes:

http://www.lispworks.com/documentation/HyperSpec/Body/03_abac.htm

Certain specific symbols and conses might also happen to be
``self-evaluating'' but only as a special case of a more general
set of rules for the evaluation of symbols and conses; such
objects are not considered to be self-evaluating objects.

Yeah, I read that while I was writing my last message in this thread.
Notice that this is just defining the term "self-evaluating object" --
it is not trying to go so far as to say that keywords aren't
"self-evaluating", only that keywords aren't "self-evaluating OBJECTS".
The standard doesn't actually try to define the term "self-evaluating"
at all. (I don't remember whether the glossary is part of the standard
proper or whether it is just the product of Kent Pitman's hard work, but
notice that there is no glossary entry for "self-evaluating", only
"self-evaluating object".)

But then the OP did in fact ask for a way to define new "self-evaluating
objects". Was he trying to use that phrase as the standard explicitly
defines it? I doubt it. But at this point I think there is no more
room on this pin head for any more angels.

- Alan
Kaz Kylheku
2023-04-17 07:38:49 UTC
Permalink
Post by Madhu
http://www.lispworks.com/documentation/HyperSpec/Body/03_abac.htm
Certain specific symbols and conses might also happen to be
``self-evaluating'' but only as a special case of a more general
set of rules for the evaluation of symbols and conses; such
objects are not considered to be self-evaluating objects.
In my opinion, this is mostly just bullshitting; text like this serves
no purpose in a specification.

All evaluation takes place under a set of rules. The fact that
an array is self-evaluating is an evaluation rule which says that
that type of object is given no special interpretation by the
evaluator, and is just regurgitated.

The rule which says that a keyword symbol evaluates to itself
is a bird of the same kind of feather. The object obj is inspected
and found to be a (keyword obj), and therefore regurigated
as if it were quoted.

Both vectorp and keyword are just properties of the object,
which are referenced by the evaluation rules.

Distinguishing special cases among general rules is just
moving some invisible goalposts around.
Post by Madhu
Yeah, I read that while I was writing my last message in this thread.
Notice that this is just defining the term "self-evaluating object" --
it is not trying to go so far as to say that keywords aren't
"self-evaluating", only that keywords aren't "self-evaluating OBJECTS".
Well, yes; it is saying that keywords aren't really self-evaluating,
because it immediately follows text which says any form that is not a
symbol or cons is self-evaluating. So that leaves in question symbols
and conses. It doesn't confirm that any of those are; only that
those which appear to be actually may not be.

BTW, what are examples of apparently self-evaluating conses?

This isn't one:

((LAMBDA (X) (LIST X (LIST 'QUOTE X))) '(LAMBDA (X) (LIST X (LIST 'QUOTE
X))))

it produces a new, similar object; the object's value is not EQL
to the object.

This one doesn't have that problem: it is self-evaluating:

#1=(quote #1#)

and it's *not* really due to any "special case" among the general rules,
either.

For that one I would tend to accept the goalposts: it's not
self-evalatuing due to any rule (special OR general) which designates
that object as self-evaluating, but due to quoting itself via circular
embedding. (CL compilers are not required to support circular syntax.)
Tom Russ
2023-04-13 01:15:33 UTC
Permalink
Post by James Cloos
does cl support defining new self-evaluating objects
(other than keywords)?
if so, how?
What sort of "defining" did you have in mind.
One simple answer (for symbols) would be:
(defconstant foo 'foo)

There may be other things you could do via reader macros.
One example of that is https://github.com/lispm/measures [*], which defined
numbers with dimensions and optional reader macros so that something like
35km or 18m/s2 would evaluate to equivalent objects, although not in an EQ sense.



[* Software by Rainer Joswig that I extended while at ISI]
Tom Russ
2023-04-13 01:18:26 UTC
Permalink
Post by Tom Russ
Post by James Cloos
does cl support defining new self-evaluating objects
(other than keywords)?
if so, how?
What sort of "defining" did you have in mind.
(defconstant foo 'foo)
There may be other things you could do via reader macros.
One example of that is https://github.com/lispm/measures [*], which defined
numbers with dimensions and optional reader macros so that something like
35km or 18m/s2 would evaluate to equivalent objects, although not in an EQ sense.
A clarification, I meant that two instances of 35km and 35km would be equivalent
objects. And likewise for 18m/s2 and 18m/s2. As expected, 35km and 18m/s2 are
not equivalent.
Post by Tom Russ
[* Software by Rainer Joswig that I extended while at ISI]
James Cloos
2023-04-13 20:37:49 UTC
Permalink
TR> One simple answer (for symbols) would be:
TR> (defconstant foo 'foo)

now i'm feeling stupid. ☺

that accomplished exactly what i was thiking of.

thanks.

-JimC
--
James Cloos <***@jhcloos.com> OpenPGP: 0x997A9F17ED7DAEA6
HenHanna
2024-10-21 22:36:08 UTC
Permalink
Post by Tom Russ
Post by James Cloos
does cl support defining new self-evaluating objects
(other than keywords)?
if so, how?
What sort of "defining" did you have in mind.
(defconstant foo 'foo)
There may be other things you could do via reader macros.
One example of that is https://github.com/lispm/measures [*], which defined
numbers with dimensions and optional reader macros so that something like
35km or 18m/s2 would evaluate to equivalent objects, although not in an EQ sense.
[* Software by Rainer Joswig that I extended while at ISI]
Do we have Defconstant in Scheme ???

Kaz Kylheku
2023-04-14 05:17:59 UTC
Permalink
Post by James Cloos
does cl support defining new self-evaluating objects
(other than keywords)?
All objects are self-evaluating other than compound
forms (non-empty list syntax), and bindable symbols.
Post by James Cloos
if so, how?
searching didn’t return any help.
i looked through the sbcl src to see how t is defined, but could not
find it. nor did i find the code responsible for keywords...
Ah, if you mean new symbols which evaluate to themselves,
and are not the keywords or T or NIL?

The obvious way is to just bind them as lexical variables
(or perhaps globals) or macros.

E.g.

(define-symbol-macro foo 'foo)

Now when foo is evaluated, it goes to (quote foo) which goes to foo.
James Cloos
2023-04-15 19:15:09 UTC
Permalink
KK> 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.

-JimC
--
James Cloos <***@jhcloos.com> OpenPGP: 0x997A9F17ED7DAEA6
Kaz Kylheku
2023-04-16 00:07:52 UTC
Permalink
Post by James Cloos
KK> 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
Madhu
2023-04-17 08:42:37 UTC
Permalink
[more of the same, sry]
Post by Kaz Kylheku
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.
This must be some sort of etymological fallacy. A variable is a binding
in the variable namespapce. Just because the word "variable" is used,
it doesn't mean that the BINDING must CHANGE ("but you said variable")

it is OK to have variables whose bindings do not change.
Loading...