加载Quicklisp的:cl21包时如何批量优先解决与:cl包的命名冲突?
批量解决CL21与CL包的命名冲突问题
我在加载Quicklisp的:cl21(Common Lisp for the 21st Century)包时,碰到了和:cl包大量命名冲突的情况——这其实是CL21的设计初衷,但逐个手动处理冲突符号实在太繁琐了。
手动解决的痛点
目前我只能通过这种方式逐个遮蔽冲突符号,但要处理上百个符号,效率极低:
(defpackage :my-pkg (:use :cl :cl21) (:shadowing-import-from :cl21.core.hash-table :hash-table-count) (:shadowing-import-from :cl21.core.sequence :position :substitute-if) (:shadowing-import-from :cl21.core.package :rename-package :use-package) (:shadowing-import-from :closer-mop :standard-generic-function) ...)
自己尝试的宏方案
为了简化这个过程,我写了一个defpackage*宏,它会自动展开成包含批量遮蔽导入的defpackage形式:
(defun package-externals (pkg-name) "Returns the external symbols in a named package." (let (pkg-syms) (do-external-symbols (sym (find-package pkg-name) pkg-syms) (push (list pkg-name sym) pkg-syms)))) (defmacro defpackage* (pkg-name use-list shadow-pkg-names) "Adds shadowing imports from a list of package names." (let ((shadow-externals (loop for pkg in shadow-pkg-names append (package-externals pkg)))) `(defpackage ,pkg-name ,use-list ,@(loop for ext in shadow-externals collect `(:shadowing-import-from ,@ext)))))
这个宏的第三个参数shadow-pkg-names是需要提取导出符号的包名列表,调用示例如下:
(defpackage* :my-pkg (:use :cl :cl21) (:cl21.core.hash-table :cl21.core.sequence :cl21.core.package ...))
遇到的疑问
不过现在我还有几个困惑:
- 我不知道怎么从
:cl21这个Quicklisp系统里自动获取完整的子包列表——我手动统计过CL21有30个子包,每个子包导出的符号数量不同,手动罗列实在太麻烦。 - 从通用角度来看,这种用宏批量导入并遮蔽的方式,是不是解决这类命名冲突的最简方案?
另外,我之前看到过一篇讨论类似问题的帖子《Use package shadowing symbols》,但没太理解,可能只能借鉴里面用读取宏拼接长列表:shadowing-import-from子句的思路。
加载CL21的困惑
还有一个小问题:我每次加载:cl21都得从头执行这段代码,感觉加载过程不太直观,不知道原因是什么:
(let ((quicklisp-init (merge-pathnames "quicklisp\\setup.lisp" (user-homedir-pathname)))) (when (probe-file quicklisp-init) (load quicklisp-init))) (ql-dist:install-dist "http://dists.cl21.org/cl21.txt") (ql:quickload :cl21)
内容的提问来源于stack exchange,提问作者davypough
相关产品推荐
相关产品推荐

