Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SBCL do-symbols (and loop) return duplicate items

I have found that SBCL 'do-symbols' (and loop) return duplicate items.

Testing environment: SBCL 1.1.4 x86 on Windows

Firstly, We define some helper functions:

;; compress from Ansi-Common-Lisp
(defun compress (x)
  (labels ((rec (e x n)
             (if (null x)
                 (if (= 1 n)
                     (list e)
                     (list (list e n)))
                 (if (eq e (car x))
                     (rec e (cdr x) (1+ n))
                     (cons (if (= 1 n)
                               e
                               (list e n))
                           (rec (car x)
                                (cdr x)
                                1))))))
    (rec (car x) (cdr x) 1)))

(compress '(a a b c d d d))
;;=> ((A 2) B C (D 3))

;; This one can make the duplicate items visible:
(defun duplicates (list)
  (remove-if-not #'listp (compress (sort list #'string<))))

(duplicates '(a a b c d d d))
;;=> ((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 s r))))

When call the 'test-pack-do-symbols' on package :SB-MOP, you can see the 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 method to iterate symbols in a package, using the mighty 'loop'.

;; Now I define `test-pack-loop' 
(defun test-pack-loop (package)
  (duplicates (loop for s being each symbol in package
                   collect s)))

When call the 'test-pack-loop', you will not see the duplicate items.

(test-pack-loop :sb-mop)
;;=> NIL

But, even loop may return duplicate items 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 consistent with the Standard?

like image 636
xiepan Avatar asked May 27 '13 04:05

xiepan


People also ask

What are the SBCL symbols affected by stack-allocation?

Affected symbols: sb-c::stack-allocate-dynamic-extent, sb-c::stack-allocate-vector, and sb-c::stack-allocate-value-cells. These compiler policies were never officially supported, and turned out the be a flawed design. Remedy For code that needs stack-allocation in legacy SBCLs, conditionalize using:

What is the use of SBCL event loop?

SBCL provides a recursive event loop (serve-event) for doing non-blocking IO on multiple streams without using threads. Timeouts and Deadlines SBCL allows restricting the execution time of individual operations or parts of a computation using :timeoutarguments to certain blocking operations, synchronous timeouts and asynchronous timeouts.

What is SBCL?

About Steel Bank Common Lisp (SBCL) is a high performance Common Lisp compiler. It is open source / free software, with a permissive license. In addition to the compiler and runtime system for ANSI Common Lisp, it provides an interactive environment including a debugger, a statistical profiler, a code coverage tool, and many other extensions.

What happens when you press the INTR key in SBCL?

This has an impact on keyboard interrupt handling: pressing your terminal’s intr key (typically Control-C) will interrupt all processes in the foreground process group, including Lisp threads that SBCL considers to be notionally ‘background’. This is undesirable, so background threads are set to ignore the SIGINT signal.


1 Answers

Please refer to the Common Lisp Hyperspec which states

do-symbols iterates over the symbols accessible in package. Statements may execute more than once for symbols that are inherited from multiple packages.

like image 152
hans23 Avatar answered Oct 11 '22 06:10

hans23