[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
EQ? and procedures, numbers, etc
Date: Thursday, 21 Nov 85 13:36:39 PST
From: Will Clinger <willc%tekchips@tektronix.CSNET>
RRRS says that (EQ? x x) is always true, but it would be better if the value
returned by EQ? were undefined when applied to procedure values and numbers.
I strongly disagree.
The current wording of RRRS forces a formal semantics of Scheme to associate
locations with procedure values and numbers. These locations have no
purpose other than to make the semantics of EQ? work as in RRRS, and they
make the semantics much uglier. The ugliness of the semantics results in
more complex and less effective optimizing compilers.
I have yet to see a convincing example of this claim. Note, however, that I consider
object identity to be one of the most indispensible things about symbolic processing
and would not be likely to be willing to give up the only function which predicates
such identity regardless of whether such an example could be constructed. However,
for now perhaps you could just enumerate some of the troublesome cases for me to respond
to more specifically.
I thought that it would be a cleaner semantics if (EQ? x x) always returned
true, but I was wrong. It is actually a cleaner semantics if the value of
EQ? is unspecified when both its arguments are procedures and when both its
arguments are numbers. When strings are immutable (as in the essential
subset of Scheme) EQ? should be unspecified when both its arguments are
strings. Similarly EQ? should be unspecified when both its arguments are
characters (unless we want to insist that either (1) characters are
represented uniquely (e.g. immediates) or (2) EQ? does something
complicated).
I bet it makes things easier to be able to ignore this distinction. I don't know
if programming ease and code size are always the same as cleanliness. They are
clearly related. It's possible that even O(size) is proportional to O(clean),
but I doubt that size is proportional to clean. Eg, consider:
(DEFINE SUCCESSOR (X) (+ X 1))
(DEFINE SUCCESSOR (X)
(UNLESS (NUMBERP X) (ERROR "Don't know the successor of ~S" X))
(+ X 1))
Certainly the first program is smaller. It is probably simpler to write.
It is not be simpler to use and may be harder to use. Whether it is cleaner
seems to me to be in a gray area.
I cite as precedent the case of CALL-WITH-CURRENT-CONTINUATION. Everyone seemed to
agree that it was easier to compile/optimize code which doesn't allow returning
these upward. The argument for pushing it through was not that it made the
implementation simpler, since in fact it complicated it. It was instead the fact
that it was (a) at least possible to implement and (b) much simpler to some write
programs when this feature was available. It seems to me that the situation is
similar for EQ? -- I do not want to give up this feature. You (the compiler writer)
have to solve this problem only once. I (the programmer) will have to solve it
repeatedly if you do not solve it once for me.