显然,外部可见的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
的import
ing符号);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
复制相似问题