From 5d4256921c0d4955b1c558aa173ddc9182d9e900 Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Wed, 23 Apr 2008 11:48:06 +0000 Subject: [PATCH] remove local length? utility svn: r9420 --- collects/scheme/list.ss | 71 ++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/collects/scheme/list.ss b/collects/scheme/list.ss index 26d287215b..def26876c1 100644 --- a/collects/scheme/list.ss +++ b/collects/scheme/list.ss @@ -109,44 +109,35 @@ ;; ls ;; (append l (car ls) (loop (cdr ls))))))])) -;; utility: returns the length for a proper list, #f otherwise; does not handle -;; circular lists -(define (length? x) - (let loop ([x x] [n 0]) - (if (pair? x) - (loop (cdr x) (add1 n)) - (and (null? x) n)))) - (define (remove-duplicates l [=? equal?]) - (let ([len (length? l)]) - (unless len (raise-type-error 'remove-duplicates "list" l)) - (let ([h (cond [(< len 40) #f] - [(eq? =? eq?) (make-hasheq)] - [(eq? =? equal?) (make-hash)] - [else #f])]) - (if h - ;; Using a hash table when the list is long enough and a using `equal?' - ;; or `eq?'. The length threshold (40) was determined by trying it out - ;; with lists of length n holding (random n) numbers. - (let loop ([l l]) - (if (null? l) - l - (let ([x (car l)] [l (cdr l)]) - (if (hash-ref h x #f) - (loop l) - (begin (hash-set! h x #t) (cons x (loop l))))))) - ;; plain n^2 list traversal (optimized for common cases) - (let-syntax ([loop (syntax-rules () - [(_ search) - (let loop ([l l] [seen null]) - (if (null? l) - l - (let ([x (car l)] [l (cdr l)]) - (if (search x seen) - (loop l seen) - (cons x (loop l (cons x seen)))))))])]) - (cond [(eq? =? equal?) (loop member)] - [(eq? =? eq?) (loop memq)] - [(eq? =? eqv?) (loop memv)] - [else (loop (lambda (x seen) - (ormap (lambda (y) (=? x y)) seen)))])))))) + (unless (list? l) (raise-type-error 'remove-duplicates "list" l)) + (let ([h (cond [(< (length l) 40) #f] + [(eq? =? eq?) (make-hasheq)] + [(eq? =? equal?) (make-hash)] + [else #f])]) + (if h + ;; Using a hash table when the list is long enough and a using `equal?' + ;; or `eq?'. The length threshold (40) was determined by trying it out + ;; with lists of length n holding (random n) numbers. + (let loop ([l l]) + (if (null? l) + l + (let ([x (car l)] [l (cdr l)]) + (if (hash-ref h x #f) + (loop l) + (begin (hash-set! h x #t) (cons x (loop l))))))) + ;; plain n^2 list traversal (optimized for common cases) + (let-syntax ([loop (syntax-rules () + [(_ search) + (let loop ([l l] [seen null]) + (if (null? l) + l + (let ([x (car l)] [l (cdr l)]) + (if (search x seen) + (loop l seen) + (cons x (loop l (cons x seen)))))))])]) + (cond [(eq? =? equal?) (loop member)] + [(eq? =? eq?) (loop memq)] + [(eq? =? eqv?) (loop memv)] + [else (loop (lambda (x seen) + (ormap (lambda (y) (=? x y)) seen)))])))))