【发布时间】:2012-10-08 14:55:28
【问题描述】:
显然,外部可见的 API 是通过导出符号来发布的。但是...如果我有多个包(比如 A、B 和 C)并且 A 的导出符号并不都意味着是外部 API 的一部分——B 和 C 需要其中一些? (类似地,B 为 A 和 C 导出一些符号,为外部 API 导出一些符号;C 是“顶级”包,它所有导出的符号都是公共 API 的一部分;我想保持模块化并允许 A 隐藏其内部来自 B 和 C,所以我避免使用 '::')。
我现在的解决方案是从 C 中重新导出所有应该公开的内容,并记录公共 API 仅包含 C 的导出符号,并且人们应该远离 A 和 B 的公共符号,以免出现错误和将来内部接口更改时代码会损坏。
有没有更好的办法?
更新:这是我对 Xach 答案的理解的实现:
首先,让我完成我的示例。我想从包a 导出符号symbol-a-1 和symbol-a-2,从包b 导出符号symbol-b-1 和symbol-b-2,从包c 导出符号api-symbol-1 和api-symbol-2。只有从 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不能使用来自b的符号(在两者都已定义之后,没有来自b的b的符号a); - 语法
package:symbol基本上不能用于“私人”导出的符号(它要么只是symbol要么package::symbol)。
【问题讨论】:
-
嗯。三个很好的答案,很难选择答案。 :-)
标签: common-lisp