shadow
shadow Function
Syntax:
shadow symbol-names &optional package → t
Arguments and Values:
symbol-names—a designator for a list of string designators.
package—a package designator . The default is the current package.
Description:
shadow assures that symbols with names given by symbol-names are present in the package.
Specifically, package is searched for symbols with the names supplied by symbol-names. For each such name, if a corresponding symbol is not present in package (directly, not by inheritance), then a corresponding symbol is created with that name, and inserted into package as an internal symbol. The corresponding symbol, whether pre-existing or newly created, is then added, if not already present, to the shadowing symbols list of package.
Examples:
(package-shadowing-symbols (make-package ’temp)) → NIL
(find-symbol ’car ’temp) → CAR, :INHERITED
(shadow ’car ’temp) → T
(find-symbol ’car ’temp) → TEMP::CAR, :INTERNAL
(package-shadowing-symbols ’temp) → (TEMP::CAR)
(make-package ’test-1) → #<PACKAGE "TEST-1">
(intern "TEST" (find-package ’test-1)) → TEST-1::TEST, NIL
(shadow ’test-1::test (find-package ’test-1)) → T
(shadow ’TEST (find-package ’test-1)) → T
(assert (not (null (member ’test-1::test (package-shadowing-symbols
(find-package ’test-1))))))
(make-package ’test-2) → #<PACKAGE "TEST-2">
(intern "TEST" (find-package ’test-2)) → TEST-2::TEST, NIL
(export ’test-2::test (find-package ’test-2)) → T
(use-package ’test-2 (find-package ’test-1)) ;should not error
Side Effects:
shadow changes the state of the package system in such a way that the package consistency rules do not hold across the change.
Affected By:
Current state of the package system.
See Also:
package-shadowing-symbols, Section 11.1 (Package Concepts)
Notes:
If a symbol with a name in symbol-names already exists in package, but by inheritance, the inherited symbol becomes shadowed 3 by a newly created internal symbol.
Expanded Reference: shadow
Basic Usage: Shadowing an Inherited Symbol
shadow ensures that a symbol with the given name is present in the package and on its shadowing symbols list. If the symbol only exists through inheritance, a new local symbol is created that shadows the inherited one.
(defpackage "SHADOW-DEMO" (:use "COMMON-LISP"))
;; CAR is inherited from COMMON-LISP
(find-symbol "CAR" "SHADOW-DEMO")
=> CAR
=> :INHERITED
(shadow "CAR" "SHADOW-DEMO")
=> T
;; Now there is a local symbol that shadows CL:CAR
(find-symbol "CAR" "SHADOW-DEMO")
;; => SHADOW-DEMO::CAR
;; => :INTERNAL
(eq (find-symbol "CAR" "SHADOW-DEMO")
(find-symbol "CAR" "COMMON-LISP"))
;; => NIL
The Shadowed Symbol Appears on the Shadowing Symbols List
(defpackage "SH-LIST" (:use "COMMON-LISP"))
(package-shadowing-symbols "SH-LIST")
=> ()
(shadow "LIST" "SH-LIST")
=> T
(package-shadowing-symbols "SH-LIST")
;; => (SH-LIST::LIST)
Shadowing Prevents Name Conflicts During use-package
Shadowing is primarily used to prevent name conflicts when using packages that export symbols with the same name.
(defpackage "LIB-1-SH" (:use) (:export "PROCESS"))
(defpackage "LIB-2-SH" (:use) (:export "PROCESS"))
(defpackage "APP-SH" (:use))
(shadow "PROCESS" "APP-SH")
=> T
;; Now both can be used without conflict
(use-package "LIB-1-SH" "APP-SH")
=> T
(use-package "LIB-2-SH" "APP-SH")
=> T
;; APP-SH's own PROCESS shadows both
(find-symbol "PROCESS" "APP-SH")
;; => APP-SH::PROCESS
;; => :INTERNAL
Shadowing Multiple Names
shadow accepts a list of string designators.
(defpackage "MULTI-SH" (:use "COMMON-LISP"))
(shadow '("CAR" "CDR" "CONS") "MULTI-SH")
=> T
(sort (mapcar #'symbol-name (package-shadowing-symbols "MULTI-SH")) #'string<)
=> ("CAR" "CDR" "CONS")
Shadowing an Already-Present Symbol
If a symbol with the given name is already present (not just inherited), shadow simply adds it to the shadowing list without creating a new symbol.
(defpackage "ALREADY-SH" (:use))
(intern "MINE" "ALREADY-SH")
(shadow "MINE" "ALREADY-SH")
=> T
;; The existing symbol is now a shadowing symbol
(package-shadowing-symbols "ALREADY-SH")
;; => (ALREADY-SH::MINE)