User Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cl:macros:with-package-iterator [2019/07/14 17:00]
cl:macros:with-package-iterator [2019/10/19 05:00] (current)
Line 1: Line 1:
 +====== Macro WITH-PACKAGE-ITERATOR ======
 +
 +====Syntax====
 +  * **with-package-iterator** (//name// //​package-list-form//​ ''&​rest''​ //​symbol-types//​) //​declaration//''​*''​ //​form//''​*''​ → //​result//''​*''​
 +
 +====Arguments and Values====
 +  * //name// - a //​[[CL:​Glossary:​symbol]]//​.
 +  * //​package-list-form//​ - a //​[[CL:​Glossary:​form]]//;​ evaluated once to produce a //​package-list//​.
 +  * //​package-list//​ - a //​[[CL:​Glossary:​designator]]//​ for a list of //​[[CL:​Glossary:​package designators]]//​.
 +  * //​symbol-type//​ - one of the //​[[CL:​Glossary:​symbol|symbols]]//​ **'':​internal''​**,​ **'':​external''​**,​ or **'':​inherited''​**.
 +  * //​declaration//​ - a **[[CL:​Symbols:​declare]]** //​[[CL:​Glossary:​expression]]//;​ not evaluated.
 +  * //forms// - an //​[[CL:​Glossary:​implicit progn]]//.
 +  * //results// - the //​[[CL:​Glossary:​values]]//​ of the //forms//.
 +
 +====Description====
 +Within the lexical scope of the body //forms//, the //name// is defined via **[[CL:​Special Operators:​macrolet]]** such that successive invocations of ''​(//​name//​)''​ will return the //​[[CL:​Glossary:​symbol|symbols]]//,​ one by one, from the //​[[CL:​Glossary:​package|packages]]//​ in //​package-list//​.
 +
 +It is unspecified whether //​[[CL:​Glossary:​symbol|symbols]]//​ inherited from multiple //​[[CL:​Glossary:​package|packages]]//​ are returned more than once. The order of //​[[CL:​Glossary:​symbol|symbols]]//​ returned does not necessarily reflect the order of //​[[CL:​Glossary:​package|packages]]//​ in //​package-list//​. When //​package-list//​ has more than one element, it is unspecified whether duplicate //​[[CL:​Glossary:​symbol|symbols]]//​ are returned once or more than once.
 +
 +//​symbol-types//​ controls which //​[[CL:​Glossary:​symbol|symbols]]//​ that are //​[[CL:​Glossary:​accessible]]//​ in a //​[[CL:​Glossary:​package]]//​ are returned as follows:
 +
 +===:​internal===
 +The //​[[CL:​Glossary:​symbol|symbols]]//​ that are //​[[CL:​Glossary:​present]]//​ in the //​[[CL:​Glossary:​package]]//,​ but that are not //​[[CL:​Glossary:​exported]]//​.
 +
 +===:​external===
 +The //​[[CL:​Glossary:​symbol|symbols]]//​ that are //​[[CL:​Glossary:​present]]//​ in the //​[[CL:​Glossary:​package]]//​ and are //​[[CL:​Glossary:​exported]]//​.
 +
 +===:​inherited===
 +The //​[[CL:​Glossary:​symbol|symbols]]//​ that are //​[[CL:​Glossary:​exported]]//​ by used //​[[CL:​Glossary:​package|packages]]//​ and that are not //​[[CL:​Glossary:​shadowed]]//​.
 +
 +When more than one argument is supplied for //​symbol-types//,​ a //​[[CL:​Glossary:​symbol]]//​ is returned if its //​[[CL:​Glossary:​accessibility]]//​ matches any one of the //​symbol-types//​ supplied. Implementations may extend this syntax by recognizing additional symbol accessibility types.
 +
 +An invocation of ''​(//​name//​)''​ returns four values as follows:
 +
 +  * 1. A flag that indicates whether a //​[[CL:​Glossary:​symbol]]//​ is returned (true means that a //​[[CL:​Glossary:​symbol]]//​ is returned). ​
 +  * 2. A //​[[CL:​Glossary:​symbol]]//​ that is //​[[CL:​Glossary:​accessible]]//​ in one the indicated //​[[CL:​Glossary:​package|packages]]//​. ​
 +  * 3. The accessibility type for that //​[[CL:​Glossary:​symbol]]//;​ i.e. one of the symbols **'':​internal''​**,​ **'':​external''​**,​ or **'':​inherited''​**. ​
 +  * 4. The //​[[CL:​Glossary:​package]]//​ from which the //​[[CL:​Glossary:​symbol]]//​ was obtained. The //​[[CL:​Glossary:​package]]//​ is one of the //​[[CL:​Glossary:​package|packages]]//​ present or named in //​package-list//​.
 +
 +After all //​[[CL:​Glossary:​symbol|symbols]]//​ have been returned by successive invocations of **[[CL:​Functions:​(//​name//​)]]**,​ then only one value is returned, namely **[[CL:​Constant Variables:​nil]]**.
 +
 +The meaning of the second, third, and fourth //​[[CL:​Glossary:​values]]//​ is that the returned //​[[CL:​Glossary:​symbol]]//​ is //​[[CL:​Glossary:​accessible]]//​ in the returned //​[[CL:​Glossary:​package]]//​ in the way indicated by the second return value as follows:
 +
 +===:​internal===
 +Means //​[[CL:​Glossary:​present]]//​ and not //​[[CL:​Glossary:​exported]]//​.
 +
 +===:​external===
 +Means //​[[CL:​Glossary:​present]]//​ and //​[[CL:​Glossary:​exported]]//​.
 +
 +===:​inherited===
 +Means not //​[[CL:​Glossary:​present]]//​ (thus not //​[[CL:​Glossary:​shadowed]]//​) but inherited from some used //​[[CL:​Glossary:​package]]//​.
 +
 +It is unspecified what happens if any of the implicit interior state of an iteration is returned outside the dynamic extent of the **with-package-iterator** form such as by returning some //​[[CL:​Glossary:​closure]]//​ over the invocation //​[[CL:​Glossary:​form]]//​.
 +
 +Any number of invocations of **with-package-iterator** can be nested, and the body of the innermost one can invoke all of the locally //​[[CL:​Glossary:​established]]//​ //​[[CL:​Glossary:​macros]]//,​ provided all those //​[[CL:​Glossary:​macros]]//​ have distinct names.
 +
 +====Examples====
 +The following function should return **[[CL:​Constant Variables:​t]]** on any //​[[CL:​Glossary:​package]]//,​ and signal an error if the usage of **with-package-iterator** does not agree with the corresponding usage of **[[CL:​Macros:​do-symbols]]**.
 +
 +<​blockquote> ​
 +([[CL:​Macros:​defun]] test-package-iterator (package) ​
 +  ([[CL:​Macros:​unless]] ([[CL:​Functions:​packagep]] package) ​
 +    ([[CL:​Macros:​setf]] package ([[CL:​Functions:​find-package]] package)))
 +  ([[CL:​Special Operators:​let]] ((all-entries '​()) ​
 +        (generated-entries '()))
 +    ([[CL:​Macros:​do-symbols]] (x package) ​
 +      ([[CL:​Macros:​multiple-value-bind]] (symbol accessibility) ​
 +          ([[CL:​Functions:​find-symbol]] ([[CL:​Functions:​symbol-name]] x) package) ​
 +        ([[CL:​Macros:​push]] ([[CL:​Functions:​list]] symbol accessibility) all-entries)))
 +    (with-package-iterator ​
 +        (generator-fn package :internal :external :​inherited) ​
 +      ([[CL:​Macros:​loop]] ​
 +        ([[CL:​Macros:​multiple-value-bind]] (more? symbol accessibility pkg) 
 +            (generator-fn)
 +          ([[CL:​Macros:​unless]] more? ([[CL:​Macros:​return]])) ​
 +          ([[CL:​Special Operators:​let]] ((l ([[CL:​Macros:​multiple-value-list]] ​
 +                     ​([[CL:​Functions:​find-symbol]] ([[CL:​Functions:​symbol-name]] symbol) package))))
 +            ([[CL:​Macros:​unless]] ([[CL:​Functions:​equal]] l ([[CL:​Functions:​list]] symbol accessibility)) ​
 +              ([[CL:​Functions:​error]] "​Symbol ~S not found as ~S in package ~A [~S]"
 +                     ​symbol accessibility ([[CL:​Functions:​package-name]] package) l))
 +            ([[CL:​Macros:​push]] l generated-entries)))))
 +    ([[CL:​Macros:​unless]] ([[CL:​Macros:​and]] ([[CL:​Functions:​subsetp]] all-entries generated-entries :test #'​[[CL:​Functions:​equal]]) ​
 +                 ​([[CL:​Functions:​subsetp]] generated-entries all-entries :test #'​[[CL:​Functions:​equal]]))
 +      ([[CL:​Functions:​error]] "​Generated entries and Do-Symbols entries don't correspond"​)) ​
 +    [[CL:​Constant Variables:​t]])) <​r>​TEST-PACKAGE-ITERATOR</​r>​
 +</​blockquote>​
 +
 +The following function prints out every //​[[CL:​Glossary:​present]]//​ //​[[CL:​Glossary:​symbol]]//​ (possibly more than once):
 +
 +<​blockquote>​
 +([[CL:​Macros:​defun]] print-all-symbols () 
 +  (with-package-iterator ​
 +      (next-symbol ([[CL:​Functions:​list-all-packages]]) :internal :external)
 +    ([[CL:​Macros:​loop]] ​
 +      ([[CL:​Macros:​multiple-value-bind]] (more? symbol) (next-symbol)
 +        ([[CL:​Special Operators:​if]] more? 
 +            ([[CL:​Functions:​print]] symbol) ​
 +            ([[CL:​Macros:​return]])))))) <​r>​PRINT-ALL-SYMBOLS</​r>​
 +</​blockquote>​
 +
 +====Side Effects====
 +None.
 +
 +====Affected By====
 +None.
 +
 +====Exceptional Situations====
 +**with-package-iterator** signals an error of type **[[CL:​Types:​program-error]]** if no //​symbol-types//​ are supplied or if a //​symbol-type//​ is not recognized by the implementation is supplied.
 +
 +The consequences are undefined if the local function named //name// //​[[CL:​Glossary:​established]]//​ by **with-package-iterator** is called after it has returned //​[[CL:​Glossary:​false]]//​ as its //​[[CL:​Glossary:​primary value]]//.
 +
 +====See Also====
 +  * {\secref\TraversalRules}
 +
 +====Notes====
 +None.
 +
 +\issue{DECLS-AND-DOC} \issue{HASH-TABLE-PACKAGE-GENERATORS:​ADD-WITH-WRAPPER} \issue{MAPPING-DESTRUCTIVE-INTERACTION:​EXPLICITLY-VAGUE}