Recently Written · git

len-cmp

Efficient comparsion of length in lists.

git clone https://github.com/equwal/len-cmp

Log | Files | Refs


length.lisp (1484 bytes)

1 (in-package :cl-user)
2 (defpackage #:len-cmp
3   (:use #:cl)
4   (:export :len))
5 (in-package :len-cmp)
6 
7 ;;;; An attempt to define an efficient length comparator.
8 #+5am (5am:def-suite length-tests :description "Test length functions.")
9 #+5am (5am:in-suite length-tests)
10 
11 (in-package :len-cmp)
12 
13 (defun null0 (list)
14   "Normalize a list variable to be numeric for length computation."
15   (if (null list) 0 1))
16 
17 #+5am (5am:test null0 (5am:is-true (and (= 1 (null0 '(1)))
18                                         (= 0 (null0 nil)))))
19 
20 (defun len (a b &optional predicate)
21   "Compare length in a variety of efficient ways."
22   (let ((predicate (if predicate predicate #'=)))
23     (if (integerp a)
24         (len-int a b predicate)
25         (len-list a b predicate))))
26 
27 (defun len-int (a b predicate)
28   (declare (integer a)
29            ((or null cons) b))
30   (if (or (= 0 a) (null b))
31       (funcall predicate a (null0 b))
32       (len-int (1- a) (cdr b) predicate)))
33 
34 (defun len-list (a b predicate)
35   (declare ((or null cons) a b))
36   (if (and a b)
37       (len-list (cdr a) (cdr b) predicate)
38       (funcall predicate (null0 a) (null0 b))))
39 
40 #+5am (5am:test len-list (5am:is-true (and (len '(1) '(1 2) #'<)
41                                            (len '(1) '(1) #'=))))
42 #+5am (5am:test len-int (5am:is-true (and (len 1 '(1))
43                                           (len 0 nil)
44                                           (not (len 1 '(1 2)))
45                                           (not (len 1 nil)))))