Neither memq nor member:test is the right thing in many cases, and
neither memq nor member:test are as efficient as they should be (I am
testing in GCL; I don't know about other Lisps). Changing memq to
member:test is just silly and annoying. If the effort is going to go
into changing these things, let's change them correctly.
They are not the right thing because they are often being used for
standard operations on Maxima internal representation, for example
(memq 'simp (caar x)) really means "is x flagged as simplified?".
Arguably more readable would be (simp-flaggedp x); though you could
also argue that using a standard operator like memq is just as good
(just as (+ x 1) is probably as readable or more than (1+ x)).
Not only does this have the advantage of saying explicitly what the
purpose of the operation is, but, it can be optimized for the vastly
most common case, namely that the op is either (op) or (op simp):
(defsubst simp-flaggedp (x)
(or (not (null (cdar x)))
(eq (cadar x) 'simp)
(memq 'simp (cdar x))))
Unfortunately, defsubst isn't standard, and the GCL compiler is pretty
simple-minded, not recognizing that (cdar x) is a common
subexpression, or how to implement not-null fast, so for efficiency
this would have to be rewritten as
(defmacro simp-flaggedp (x)
`(let ((cdarx (cdar ,x)))
(if cdarx
(or (eq (car cdarx) 'simp)
(memq 'simp cdarx))
;;Function call rarely called, so use a shorter but
;; slower code sequence in this case rather than member
;; which gives an inline loop
nil)))
For the (member a '(x y)) case, you'd hope that member would unroll
the loop for a short list like this one -- which GCL does -- and also
notice that an eq-test is equivalent to an eql-test when the elements
are symbols (thus avoiding the need for :test completely) -- which it
doesn't (compiler bug? it does compile (eql a 'x) as (eq a 'x)).
Finally, it is just ridiculous to make these multiple textual changes
because member:test is faster than memq when the change can be
implemented trivially by changing memq to a macro.
-s