显然,外部可见的 API 是通过导出符号来发布的。但是......如果我有多个包(比如 A、B 和 C)并且 A 的导出符号并不都是外部 API 的一部分——B 和 C 需要其中的一些?(类似地,B 为 A 和 C 导出一些符号,为外部 API 导出一些符号;C 是“顶级”包,它所有导出的符号都是公共 API 的一部分;我想保持模块化并允许 A 隐藏其内部来自 B 和 C,所以我避免使用 '::')。
我现在的解决方案是从 C 重新导出所有应该公开的内容,并记录公共 API 仅包含 C 的导出符号,人们应该远离 A 和 B 的公共符号,因为错误和代码被破坏内部接口改变的未来。
有没有更好的办法?
更新:这是我对 Xach 回答的理解的实现:
首先,让我完成我的示例。我想导出符号symbol-a-1
和symbol-a-2
包a
,符号symbol-b-1
和symbol-b-2
包b
和符号api-symbol-1
以及api-symbol-2
包c
。只有从中导出的符号c
是公共 API 的一部分。
首先, 的定义a
:
(defpackage #:a
(:use #:cl))
请注意,没有任何导出的符号:-)
辅助宏(使用 Alexandria):
(defmacro privately-export (package-name &body symbols)
`(eval-when (:compile-toplevel :load-toplevel :execute)
(defun ,(alexandria:format-symbol *package*
"IMPORT-FROM-~a"
(symbol-name package-name)) ()
(list :import-from
,package-name
,@(mapcar (lambda (to-intern)
`',(intern (symbol-name to-intern) package-name))
symbols)))))
使用宏“私下导出”:-):
(privately-export :a :symbol-a-1 :symbol-a-2)
现在定义b
:
(defpackage #:b
(:use #:cl)
#.(import-from-a))
... b
'出口':
(privately-export :b :symbol-b-1 :symbol-b-2)
...c
的定义:
(defpackage #:c
(:use #:cl)
#.(import-from-a)
#.(import-from-b)
(:export :api-symbol-1 :api-symbol-2)
这种方法的问题:
a
不能使用符号 fromb
(在两者都被定义后没有import
ing 符号 fromb
froma
);- 该语法
package:symbol
基本上不适用于“私人”导出的符号(它只是symbol
或package::symbol
)。