Use package shadowing symbols

那年仲夏 提交于 2019-12-23 19:50:39

问题


For instance I have this package definition which shadows COMMON-LISP:LISTEN :

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

And then I want to use this package from another package, say

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

What is the purpose of shadow if I cannot actually override Common Lisp symbols when using the package ?


回答1:


Simple

The :shadow argument to defpackage affects the definition of the package shadows, not the later use of shadows in light.

You need to use 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.

Bulk

If you need to do bulk shadowing, you would need to use individual functions (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.

You might find macroexpand-1 useful in decising how get where you need to go:

(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. Shadowing ANSI CL standard names is not a very good idea for your code readability.




回答2:


OK so there actually is a handy way to do this.

In my many-shadows package I export a shadowing-import-from function. It looks like this :

(defun shadowing-import-from ()
  `(:shadowing-import-from :many-shadows
     ,@(package-shadowing-symbols :many-shadows)))

And then, in the light defpackage I just READ-EVAL it :

(defpackage :light
  (:use :common-lisp
        :many-shadows)
  #.(many-shadows:shadowing-import-from))

So it is explicit that something was shadowed and that I want to use the symbols from many-shadows in priority. And it is short enough to be documented and used pragmatically.

Thank you @sds for pointing me to :shadowing-import-from.




回答3:


What is the purpose of shadow if I cannot actually override Common Lisp symbols when using the package?

The purpose of a package having a list of shadowing symbols is to resolve conflicts arising from package use by that package. Shadowing has no effect on anything exported.

When a package uses others, conflicts can arise when two or more used packages export a symbol by the same name. Similarly, conflicts can also arise between a used package and symbols in the local package. These conflicts are treated as errors. On a symbol-by-symbol basis, shadowing squelches these conflicts. A symbol, which is present in the package, is added to its list of shadowing symbols. Any conflict is then silently resolved in favor of that symbol.

Being a shadowing symbol doesn't bestow any special powers on a symbol when it is regarded from outside the package where it has that status.

For each package, we have to separately arrange the "visibility stack", including its own shadowing symbols, if necessary.



来源:https://stackoverflow.com/questions/44596132/use-package-shadowing-symbols

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!