Rich,
Since you're going to do this by hand anyway, why not take the
opportunity to separate out the simpp case?
This might make the code a little clearer, which is a clear benefit.
I don't get the impression that speed is a big deal for the vast
majority of our users (though a few do in fact do very large
calculations where even 10% makes a difference), but by
special-casing the overwhelmingly common cases (based on a quick test
I just did), you can speed things up as well.
(memq 'simp (cdar x)) => (simp-flagged expr)
where simp-flagged is the macro equivalent of
(defun simp-flagged (ex)
(let ((p (cdar ex)))
(cond ((null p) nil) ; about 1/2 the time
((eq (car p) 'simp) t) ; about 1/2 the time
(t (member-eq 'simp (cdr p)))))) ; uncommon case, do an
out-of-line func call
Doing the uncommon case out of line may improve performance over an
inline loop (cache line/prefetch effects).
> I also put in a macro memq2 that is good if the 2nd arg is exactly 2 long,
> which seems to be most of the time.
If the second arg is a constant, then loop unrolling (in the macro) is
probably a good idea for length < 5 or so, not just length < 3. It
seems that some compilers already do this, but not GCL. Dumb compilers
would probably also benefit from a boolean-valued memq.
-s