例如,我有这个包定义影响COMMON-LISP:LISTEN:
(defpackage :shadows
(:use :common-lisp)
(:shadow #:listen)
(:export #:listen))
然后我想从另一个包中使用这个包,比如说
(defpackage :light
(:use :common-lisp
:shadows))
如果在使用包时我无法实际覆盖Common Lisp符号,那么shadow的目的是什么?
答案 0 :(得分:3)
defpackage
的:shadow
参数
影响包shadows
的定义,
不是shadows
中light
的后期使用。
您需要使用shadowing-import
:
(defpackage #:shadows
(:use #:common-lisp)
(:shadow #:listen)
(:export #:listen))
(defpackage #:light
(:shadowing-import-from #:shadows #:listen)
(:use #:common-lisp #:shadows))
(eq 'light::listen 'shadows:listen)
==> T
(describe 'light::listen)
==>
SHADOWS:LISTEN is the symbol SHADOWS:LISTEN, lies in #<PACKAGE SHADOWS>,
is accessible in 2 packages LIGHT, SHADOWS.
#<PACKAGE SHADOWS> is the package named SHADOWS.
It imports the external symbols of 1 package COMMON-LISP and
exports 1 symbol to 1 package LIGHT.
如果您需要进行批量阴影,则需要使用单个函数
(make-package
,
import
,
export
,
shadow
,
use-package
):
(defparameter *my-shadow-list* '(#:car #:cdr))
(make-package '#:my-package :use nil)
(import *my-shadow-list* '#:my-package)
(export *my-shadow-list* '#:my-package)
(shadow *my-shadow-list* '#:my-package)
(use-package '#:cl '#:my-package)
(make-package '#:my-user)
(shadowing-import *my-shadow-list* '#:my-user)
(use-package '(#:cl #:my-package) '#:my-user)
(describe 'my-user::car)
==>
MY-PACKAGE:CAR is the symbol MY-PACKAGE:CAR, lies in #<PACKAGE MY-PACKAGE>,
is accessible in 2 packages MY-PACKAGE, MY-USER.
#<PACKAGE MY-PACKAGE> is the package named MY-PACKAGE.
It imports the external symbols of 1 package COMMON-LISP and
exports 2 symbols to 1 package MY-USER.
您可能会发现macroexpand-1
在决定如何到达目的地方面非常有用:
(macroexpand-1 '(defpackage #:light
(:shadowing-import-from #:shadows #:listen)
(:use #:common-lisp #:shadows)))
==>
(EVAL-WHEN (:COMPILE-TOPLEVEL :LOAD-TOPLEVEL :EXECUTE)
(SYSTEM::%IN-PACKAGE "LIGHT" :NICKNAMES 'NIL :USE 'NIL :CASE-SENSITIVE NIL
:CASE-INVERTED NIL)
(SYSTEM::SHADOWING-IMPORT-CERROR "LISTEN" "SHADOWS" NIL "LIGHT")
(USE-PACKAGE '("COMMON-LISP" "SHADOWS") "LIGHT") (FIND-PACKAGE "LIGHT")) ;
T
PS。隐藏ANSI CL标准名称对于代码可读性来说不是一个好主意。
答案 1 :(得分:3)
好的,所以实际上有一种方便的方法。
在我的多阴影包中,我导出了一个shadowing-import-from
函数。它看起来像这样:
(defun shadowing-import-from ()
`(:shadowing-import-from :many-shadows
,@(package-shadowing-symbols :many-shadows)))
然后,在光线拆包中,我只是阅读它:
(defpackage :light
(:use :common-lisp
:many-shadows)
#.(many-shadows:shadowing-import-from))
因此明确表示某些内容被遮蔽,我希望优先使用多阴影中的符号。它足够短,可以记录并以务实的方式使用。
感谢@sds指点我:shadowing-import-from
。
答案 2 :(得分:1)
如果在使用包时我无法覆盖Common Lisp符号,那么shadow的目的是什么?
具有阴影符号列表的包的目的是解决由该包使用包引起的冲突。阴影对导出的任何内容都没有影响。
当包使用其他包时,当两个或多个使用的包以相同名称导出符号时,可能会发生冲突。类似地,在本地包中使用的包和符号之间也可能发生冲突。这些冲突被视为错误。在逐个符号的基础上,阴影压制了这些冲突。包中存在的符号将添加到其阴影符号列表中。然后,任何冲突都会默默地解决,以支持该符号。
作为一个阴影符号,当它从具有该状态的包裹外部被视为符号时,不会赋予符号任何特殊权力。
对于每个包,我们必须单独安排“可见性堆栈”,包括必要的阴影符号。