Udyant Wig <
udy...@gmail.com> wrote:
+---------------
| Suppose that a character has to be checked against a list of possible
| values. What form of predicate is to be preferred?
|
| (defun char-of-interest-1-p (ch)
| (member ch (list char1 char2 char3 char4)))
+---------------
First, with this form you almost never want to build the search list
at runtime. [I'm assuming "char1" here is a metavariable for an actual
character literal, not a real variable *containing* a character.]
So use either this:
(defun char-of-interest-1-p (ch)
(member ch '(#\A #\c #\E #\g)))
or [especially if "charN" *are* variables!]:
(defun char-of-interest-1-p (ch)
(member ch (load-time-value (list char1 char2 char3 char4))))
{And ignore what I just said if the "charN" are *mutable* variables
and *are* mutated during execution.]
+---------------
| (defun char-of-interest-2-p (ch)
| (or (eq ch char1)
| (eq ch char2)
| (eq ch char3)
| (eq ch char4)))
+---------------
Similar comments for this one, except that (a) it's longer;
(b) the MEMBER version might be faster; and (c) it's not even
guaranteed to *work* at all!!! As CLHS "Function EQ" says:
An implementation is permitted to make ``copies'' of characters
and numbers at any time. The effect is that Common Lisp makes
no guarantee that eq is true even when both its arguments are
``the same thing'' if that thing is a character or number.
So if you use this form, use EQL, not EQ.
+---------------
| (defun char-of-interest-3-p (ch)
| (case ch
| ((char1 char2 char3 char4) t)
| (otherwise nil)))
+---------------
This might generate the fastest code of the three so far, but
note that the "charN" must be literal characters, *not* variable
names, since the key list is *not* evaluated. [Note that this
also means that you can't use LOAD-TIME-VALUE with this version.]
A fourth version you might want to use -- especially if
you have a *large* number of characters in the set of
interest -- is a hash table:
(defparameter *char-of-interest-4-hash*
(let ((h (make-hash-table)))
(dolist (c (list char1 char2 char3 char4)) ;; Or (coerce "abcde" 'list), etc.
(setf (gethash c h) c)) ;; Or maybe (setf (gethash c h) t)
h))
(defun char-of-interest-4-p (ch)
(gethash ch *char-of-interest-4-hash*))
Ignoring cache effects, this lookup will be approximately
constant time no matter how many characters are in the set.
[For very small sets, MEMBER or CASE will still probably
be faster.]
-Rob
-----
Rob Warnock <
rp...@rpw3.org>
627 26th Avenue <
http://rpw3.org/>
San Mateo, CA 94403