It seems to me that the specification of ADJOIN is "wrong".
Tests whether item is the same as an existing element of list. If
the item is not an existing element, adjoin adds it to list (as if
by cons) and returns the resulting list; otherwise, nothing is added
and the original list is returned.
The test, test-not, and key affect how it is determined whether item
is the same as an element of list. For details, see Section 17.2.1
(Satisfying a Two-Argument Test).
Abd sectuib 17.2.1 says:
The function designated by the :key argument is never called on O
itself. However, if the function operates on multiple sequences
(e.g., as happens in set-difference), O will be the result of
calling the :key function on an element of the other sequence.
So, CLHS says that ADJOIN should not call key on the object to be
adjoined:
(defun adjoin* (item list &key (key (function identity))
(test (function eql))
(test-not nil test-not-p))
(if (apply (function member) item list
:key key
:test test
(when test-not-p
(list :test-not test-not)))
list
(cons item list)))
and therefore clhs specifies:
(adjoin* '(a 1) '((a 2) (b 3)) :key (function car))
--> ((a 1) (a 2) (b 3))
Of course, that's not what's implemented, in all implementations we
have:
(adjoin '(a 1) '((a 2) (b 3)) :key (function car))
--> ((a 2) (b 3))
Therefore, it seems to me there should be a clarifying issue for ADJOIN.
The specification for PUSHNEW is correct, and refers to the
expected behavior from ADJOIN. The clarifying issue for ADJOIN could
just substitute the paragraph:
The test, test-not, and key affect how it is determined whether item
is the same as an element of list. For details, see Section 17.2.1
(Satisfying a Two-Argument Test).
replacing it by:
Whether or not item is already a member of the list that is in place
is determined by comparisons using :test or :test-not. The first
argument to the :test or :test-not function is item as returned by
the :key function (if supplied); the second argument is an element
of the list in place as returned by the :key function (if supplied).
If :key is supplied, it is used to extract the part to be tested
from both item and the list element.
The argument to the :key function is an element of the list stored
in place. The :key function typically returns part part of the
element of the list. If :key is not supplied or nil, the list
element is used.
from the PUSHNEW specification. Since the specifications already makes
reference to the specification of ADJOIN, those paragraphs could just be
removed from PUSHNEW.
--
__Pascal Bourguignon__
http://www.informatimago.com/
A bad day in () is better than a good day in {}.