I found that SBCL 'do-symbols' (and loop) return duplicate elements.
Test conditions: SBCL 1.1.4 x86 on Windows
First, we define some helper functions:
;; compress from Ansi-Common-Lisp (defun compress (x) (labels ((rec (exn) (if (null x) (if (= 1 n) (list e) (list (list en))) (if (eq e (car x)) (rec e (cdr x) (1+ n)) (cons (if (= 1 n) e (list en)) (rec (car x) (cdr x) 1)))))) (rec (car x) (cdr x) 1))) (compress '(aabcddd)) ;;=> ((A 2) BC (D 3)) ;; This one can make the duplicate items visible: (defun duplicates (list) (remove-if-not #'listp (compress (sort list #'string<)))) (duplicates '(aabcddd)) ;;=> ((A 2) (D 3)) ;; This one use 'do-symbols' iterate each symbol in package, and check the ;; result (defun test-pack-do-symbols (package) (let (r) (do-symbols (s package (duplicates r)) (push sr))))
When you call "test-pack-do-symbols" on the package: SB-MOP, you can see duplicate items
(test-pack-do-symbols :sb-mop) ;;=> ((ADD-METHOD 2) (ALLOCATE-INSTANCE 2) (BUILT-IN-CLASS 2) (CLASS 2) ;; (CLASS-NAME 2) (COMPUTE-APPLICABLE-METHODS 2) (ENSURE-GENERIC-FUNCTION 2) #'2 ;; (GENERIC-FUNCTION 2) (MAKE-INSTANCE 2) (METHOD 2) (METHOD-COMBINATION 2) ;; (METHOD-QUALIFIERS 2) (REMOVE-METHOD 2) (STANDARD-CLASS 2) ;; (STANDARD-GENERIC-FUNCTION 2) (STANDARD-METHOD 2) (STANDARD-OBJECT 2) (T 2))
There is another way to iterate characters in a package using a powerful "loop".
;; Now I define `test-pack-loop' (defun test-pack-loop (package) (duplicates (loop for s being each symbol in package collect s)))
When you call the "test package-loop", you will not see duplicate elements.
(test-pack-loop :sb-mop) ;;=> NIL
But even a loop can return duplicate elements on some packages, you can use the following code to see the difference between "test-pack-do-symbols" and "test-pack-loop"
(let (r1 r2) (dolist (p (list-all-packages)) (when (test-pack-do-symbols p) (push (package-name p) r1)) (when (test-pack-loop p) (push (package-name p) r2))) (print r1) (print r2) nil)
So, is this a bug or is it standard?
source share