User Tools


====== 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}