2017-06-16 54 views
1

比如我有陰影COMMON-LISP這個包定義:聽:使用的軟件包陰影符號

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

然後我想從另一個包中使用這個包,說

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

什麼如果我在使用軟件包時無法真正覆蓋Common Lisp符號,是否是影子的目的?

+0

你可能想要做的是構建一個'like'CL'但是其中一些符號不同的包。你可能想看看[管道](https://github.com/Inaimathi/conduits),它可以讓你做到這一點。 (免責聲明:我寫了這篇文章,並且很慚愧地說我目前沒有世界可見的副本:這是別人的)。 – tfb

回答

2

簡單

:shadow參數defpackage 影響包shadows, 不light以後的使用中shadows的定義。

您需要使用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-packageimportexportshadowuse-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有用的decising如何得到你需要去:

(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標準名稱對於您的代碼可讀性來說不是一個好主意。

+0

嗯,我有幾十個這樣的符號,所以每次我想要使用這個陰影批處理包時,我都必須明確地說明:shadowing-import-from,這真是太吸引人了。我知道這不是你的錯,謝謝。 – thodg

+0

如果'DEFPACKAGE'只是堆棧使用的包符號,而不會引發衝突錯誤,那對我來說就完全沒問題。 – thodg

+0

您可以使用'shadowing-import'進行批量陰影或50年前的旅行,並說服Lisp設計師,您的「按順序堆疊使用的包符號」的想法是個好主意。請注意,當所有符號都包含在所有包中時,您將必須解釋如何從'p2'中執行'p1'和's2'的shadowing-import's1' ;-) – sds

1

行,所以確實有一個方便的方法來做到這一點。

在我的許多陰影包中,我輸出一個shadowing-import-from函數。它看起來像這樣:

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

,然後在光defpackage我剛纔讀-EVAL它:

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

因此,它是明確的東西被遮蔽並且,我想用從符號優先考慮多個陰影。而且它足夠短,可以被記錄下來並用於實際操作。

謝謝@sds指向我:shadowing-import-from

0

陰影的目的是什麼,如果我在使用包時實際上無法覆蓋Common Lisp符號?

具有陰影符號列表的包的目的是爲了解決由該包使用包產生的衝突。陰影對導出的任何內容都沒有影響。

當軟件包使用其他軟件包時,如果兩個或兩個以上使用的軟件包以相同名稱導出某個軟件包,則可能會產生衝突。同樣,在使用的軟件包和本地軟件包中的符號之間也會產生衝突。這些衝突被視爲錯誤。在逐個符號的基礎上,陰影會壓制這些衝突。包中存在的符號被添加到其陰影符號列表中。任何衝突然後默默解決,以支持這個符號。

作爲一個影子符號不會賦予符號的任何特殊權力,當它從封裝外部被視爲具有該狀態時。

對於每個包,必要時我們必須單獨安排「可見性堆棧」,包括其自己的陰影符號。