使用包阴影符号

时间:2017-06-16 18:52:01

标签: package lisp common-lisp

例如,我有这个包定义影响COMMON-LISP:LISTEN:

(defpackage :shadows
  (:use :common-lisp)
  (:shadow #:listen)
  (:export #:listen))

然后我想从另一个包中使用这个包,比如说

(defpackage :light
  (:use :common-lisp
        :shadows))

如果在使用包时我无法实际覆盖Common Lisp符号,那么shadow的目的是什么?

3 个答案:

答案 0 :(得分:3)

简单

defpackage:shadow参数 影响包shadows的定义, 不是shadowslight的后期使用。

您需要使用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的目的是什么?

具有阴影符号列表的包的目的是解决由该包使用包引起的冲突。阴影对导出的任何内容都没有影响。

当包使用其他包时,当两个或多个使用的包以相同名称导出符号时,可能会发生冲突。类似地,在本地包中使用的包和符号之间也可能发生冲突。这些冲突被视为错误。在逐个符号的基础上,阴影压制了这些冲突。包中存在的符号将添加到其阴影符号列表中。然后,任何冲突都会默默地解决,以支持该符号。

作为一个阴影符号,当它从具有该状态的包裹外部被视为符号时,不会赋予符号任何特殊权力。

对于每个包,我们必须单独安排“可见性堆栈”,包括必要的阴影符号。