(in a x) determines if
The logical definition of
The :exec version just inlines the set primitives and does one level of loop unrolling. On CCL, it seems to run about 2.6x faster on the following loop:
;; 4.703 sec logic, 1.811 sec exec (let ((big-set (loop for i from 1 to 100000 collect i))) (gc$) (time (loop for i fixnum from 1 to 30000 do (set::in i big-set))))
There are other ways we could optimize
The simplest way to do this is to use
(in 1 '(2 3 4 .... 100000))
where we could return instantly, there are also times where it would be slower. For instance, on
(in 100001 '(1 2 3 4 ... 100000))
we would incur the extra cost of 100,000 calls to
For this reason, we do not currently implement any short-circuiting. The reasoning is:
Future note. In principle membership in an ordered list might be done in
Function:
(defun in (a x) (declare (xargs :guard (setp x))) (mbe :logic (and (not (emptyp x)) (or (equal a (head x)) (in a (tail x)))) :exec (and x (or (equal a (car x)) (and (cdr x) (or (equal a (cadr x)) (in a (cddr x))))))))
Theorem:
(defthm in-type (or (equal (in a x) t) (equal (in a x) nil)) :rule-classes :type-prescription)
Theorem:
(defthm not-in-self (not (in x x)))
Theorem:
(defthm in-sfix-cancel (equal (in a (sfix x)) (in a x)))
Theorem:
(defthm never-in-empty (implies (emptyp x) (not (in a x))))
Theorem:
(defthm in-set (implies (in a x) (setp x)))
Theorem:
(defthm in-tail (implies (in a (tail x)) (in a x)))
Theorem:
(defthm in-tail-or-head (implies (and (in a x) (not (in a (tail x)))) (equal (head x) a)))
Theorem:
(defthm in-head (equal (in (head x) x) (not (emptyp x))))