Related issues: PUSH-EVALUATION-ORDER
Edit history: v1, 14 Feb 1991, Sandra Loosemore
v2, 26 Mar 1991, Sandra Loosemore (amendment from meeting)
Status: v2 (proposal UNSPECIFIED) accepted by X3J13, Mar 1991
The description of the PUSHNEW macro says contradictory things about
whether the storing form for its place subform must or must not be
evaluated in the situation where the <item> is already a member of
In CLtL, PUSHNEW is first described as:
If the <item> is not already a member of the list (...), then the
<item> is consed onto the front of the list, and the augmented list is
stored back into <place> and returned; otherwise the unaugmented list
This passage implies that PUSHNEW is effectively (modulo order of
evaluation issues and keyword arguments):
(if (not (member <item> <place>))
(setf <place> (cons <item> <place>))
which executes the storing form for <place> only if the member test
However, later on it's said that PUSHNEW is effectively (again modulo
order of evaluation issues and keyword arguments):
(setf <place> (adjoin <item> <place>))
which executes the storing form for <place> unconditionally.
So which of these two models for its expansion is correct?
Clarify that it is not specified whether PUSHNEW executes the storing
form for its <place> subform in the situation where the <item> is
already a member of the list.
The store operation might be expensive and there's no point in doing
it if the value being stored hasn't changed. On the other hand, in
some implementations PUSHNEW always does the store.
In both Lucid and Allegro, PUSHNEW always does the store.
Cost to Implementors:
None. No implementation is required to change.
Cost to Users:
Cost of non-adoption:
The description of PUSHNEW is confusing.
Not doing the store when it's not necessary can speed things up.
The cost of non-adoption is avoided.
PUSHNEW would be less confusing if we could just agree on one or
the other of the two models as being correct and remove all mention
of the other from its description in the standard.
There is a potential for generalization to other read-modify-write
macros. See the discussion section of issue SETF-GET-DEFAULT.