显然,外部可见的API是通过导出符号发布的。但是..。如果我有多个包(例如A、B和C),而A的导出符号并不都是外部API的一部分--其中一些是B和C需要的?(类似地,B为A和C导出了一些符号,为外部API导出了一些符号;C是'toplevel‘包,它导出的所有符号都是公共API的一部分;我希望保持模块化,允许A对B和C隐藏其内部,所以我避免了'::')。
我现在的解决方案是从C中再导出所有要公开的内容,并证明公共API仅由C的导出符号组成,人们应该远离A和B的公共符号,因为将来内部接口更改时会出现错误和代码中断。
有更好的办法吗?
更新:这是我对Xach答案的理解的实现:
首先,让我完成我的例子。我想从包symbol-a-1和symbol-a-2导出符号a,从package b导出符号symbol-b-1和symbol-b-2,从package 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到a的importing符号);package:symbol基本上不能用于导出‘私有’的符号(它要么是symbol,要么是package::symbol)。发布于 2012-10-18 12:46:37
如果A和B主要用于C的实现,则可以通过选择性地使用:import-from进行C的defpackage驱动,因为您可以导入非外部的内容。然后你可以有选择地从那里再出口。
发布于 2012-10-18 09:06:43
您可以添加第三个包D,它导出所有公共API符号,并将A、B和C包视为私有包。然后,可以使用限定名限定API包中所有函数和变量的定义,如
(defun D:blah () ...)
以便于直观地发现公共入口点的定义。
发布于 2012-10-18 12:18:04
也许,最简单的方法是由汉斯提出的。
你也可以看看蒂姆·布拉德肖的导管包装
https://stackoverflow.com/questions/12949749
复制相似问题