I think we must say explicitly whether (SETF GET) and (SETF GETF) are
permitted to re-order cells. Secondarily, I also think that we should
say that re-ordering is not permitted.
Among other things... You can do:
(SETQ X '(A B C D))
(SETF (GETF X 'C) 'E)
and indeed you don't have to worry whether
X => (A B C E) or (C E A B) or (C E A B C D)
if all you're going to do is
(GETF X 'C).
However, you must be much more careful about
(GET-PROPERTIES X '(A C))
which will then get
A, B, (A B C E)
or C, E, (C E A B)
or C, E, (C E A B C D)
depending on which strategy has been used.
The presence of an operator like GET-PROPERTIES in the language
acknowledges the fact that property list as we have come to use it is
not just an abstract table as some would have it be, but in fact an
ordered entry capable of doing a restartable multiple lookup. In my
view, this invites (almost begs) the user to exploit shadowing or
prioritizing. If (SETF GETF) is permitted to alter an existing ordering,
I believe that many programs which use GET-PROPERTIES will be
gratuitously broken.
It's easy to imagine writing programs which rely on the kind of side-effect
behavior I'm describing without realizing that you're doing so. If your
test cases happen not to show up the problem, it can be a real surprise
when you port. If you're lucky, things will just blow out, but often
they don't and you travel miles from the point of the error before you
notice something is wrong.
Leaving things unspecified may be nice for each individual implementation
but can be a real barrier to portability as I've learned from hard
experience with trying to get Macsyma to port.
I'm sympathetic to DLA's desire to optimize and I don't want to
trivialize the cost I'm asking him (and others) to pay. But not all of
language design can be based on worry over potentially lost optimizations.
If we thought that, we'd have said it was ok for
(+ (THE FIXNUM X) (THE FIXNUM Y))
to optimize into a fixnum add instruction. The current definition of
the language practically precludes the fixnum add instruction ever being
generated because the user is almost always (in my experience) too lazy
or otherwise unwilling to write
(THE FIXNUM (+ (THE FIXNUM X) (THE FIXNUM Y))).
The stock hardware people had to take a real performance hit on this one.
I haven't looked at the Gabriel benchmarks recently; perhaps it's kind
enough to provide a few benchmarks that suggest that people would really
write this kind of code, so perhaps it gives the impression that the
compiler can generate better code than I bet it typically does, so perhaps
it hasn't hurt the stock hardware people's sales so much. Who knows?
But in any case, the effective performance hit was the price we as a
community paid because we wanted things to port without surprises and
even though you could test your programs at the fixnum boundary points
on one machine with a particular word size, you couldn't easily anticipate
the effect of varying word sizes.
I consider the case of the destructive operations at least as important
as fixnum addition. Perhaps more so because I bet we are on the brink of
places where side-effects will bite us lots more often than we are on the
brink of places where machine word overflow will bite us.
Many CL users maintain code at one site in one or two implementations
and still want to share that code with others at other sites. The ability
to reliably debug portable code in a small number of implementations is
of key importance to those users.
I often feel like vendors want to put such portability issues at an
artificially low level. They mostly seem to want to be able to
(a) optimize the hell out of their implementation
and (b) leave enough vagueness in the spec that people will
find it painful to move out of their implementation into
someone else's. (Always in this an assumption that "the user"
begins in their own implementation and not in someone else's. :-)