package - SBCL做符号(和循环)返回重复项

标签 package common-lisp

我发现SBCL'do-symbols'(和循环)返回重复项。

测试环境:Windows上的SBCL 1.1.4 x86

首先,我们定义一些辅助函数:

;; 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))))

当在软件包:SB-MOP上调用“test-pack-do-symbols”时,您会看到重复的项目
(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))

还有一种使用强大的“循环”来迭代包中符号的方法。
;; Now I define `test-pack-loop' 
(defun test-pack-loop (package)
  (duplicates (loop for s being each symbol in package
                   collect s)))

当调用“test-pack-loop”时,您将看不到重复的项目。
(test-pack-loop :sb-mop)
;;=> NIL

但是,即使循环可能会在某些软件包上返回重复的项目,您也可以使用以下代码查看“test-pack-do-symbols”和“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)

那么,这是错误还是与标准一致?

最佳答案

请参阅Common Lisp Hyperspec,其中指出

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

关于package - SBCL做符号(和循环)返回重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16766319/

相关文章:

java - 将 Java 包添加到 GWT

java 错误 : class, 接口(interface),或预期的枚举(多进程包)

ipython - Jupyter 和 Common Lisp

performance - 使用 expt-mod 函数的 Lisp 性能问题

list - 正常函数中的反引号、反引号和反引号拼接

c - 如何最好地检查 C 库依赖性?

python - 错误 "resolve() got an unexpected keyword argument ' Replace_conflicting'"是什么意思?

arrays - 如何连接 Golang 中一个包的几个文件的数据?

recursion - 是否存在具有两个累积变量的 tco 模式?

lisp - CLISP 中的意外评估结果