1
0
Fork 0
cl-sites/HyperSpec-7-0/HyperSpec/Issues/iss188_w.htm

355 lines
30 KiB
HTML
Raw Permalink Normal View History

2024-04-01 10:24:07 +02:00
<!-- Common Lisp HyperSpec (TM), version 7.0 generated by Kent M. Pitman on Mon, 11-Apr-2005 2:31am EDT -->
<HTML>
<HEAD>
<TITLE>CLHS: Issue HASH-TABLE-PACKAGE-GENERATORS Writeup</TITLE>
<LINK HREF="../Data/clhs.css" REL="stylesheet" TYPE="text/css" />
<META HTTP-EQUIV="Author" CONTENT="Kent M. Pitman">
<META HTTP-EQUIV="Organization" CONTENT="LispWorks Ltd.">
<LINK REL=TOP HREF="../Front/index.htm">
<LINK REL=COPYRIGHT HREF="../Front/Help.htm#Legal">
<LINK REL=DISCLAIMER HREF="../Front/Help.htm#Disclaimer">
<LINK REL=PREV HREF="../Issues/iss187_w.htm">
<LINK REL=UP HREF="../Issues/iss188.htm">
<LINK REL=NEXT HREF="../Issues/iss189_w.htm">
</HEAD>
<BODY>
<H1><A REV=MADE HREF="http://www.lispworks.com/"><IMG WIDTH=80 HEIGHT=65 ALT="[LISPWORKS]" SRC="../Graphics/LWSmall.gif" ALIGN=Bottom></A><A REL=TOP HREF="../Front/index.htm"><IMG WIDTH=237 HEIGHT=65 ALT="[Common Lisp HyperSpec (TM)]" SRC="../Graphics/CLHS_Sm.gif" ALIGN=Bottom></A> <A REL=PREV HREF="../Issues/iss187_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="../Issues/iss188.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="../Issues/iss189_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
<HR>
<H2>Issue HASH-TABLE-PACKAGE-GENERATORS Writeup</H2>
<PRE><B>Forum:</B> Cleanup<P>
<B>Issue:</B> <A HREF="iss188.htm">HASH-TABLE-PACKAGE-GENERATORS</A><P>
<P>
<B>References:</B> Issue: <A HREF="iss134.htm">DO-SYMBOLS-DUPLICATES</A> <P>
<P>
<B>Category:</B> ADDITION<P>
<P>
<B>Edit history:</B> Version 1, 23-May-88 JonL<P>
Version 2, 6-Oct-88 JonL (convert to &quot;with&quot; scoping).<P>
Version 3, 7-Oct-88 JonL (mly's syntax for package iterator)<P>
Version 4, 8-Nov-88 JonL (fix example; clarify some nits)<P>
Version 5, 22-Nov-88 Moon (improve syntax for package iterator,<P>
add examples, fix typos)<P>
Version 6, 6-Oct-88 JonL (final nits)<P>
Version 7, 8-Dec-88, Masinter (add comment to discussion)<P>
<P>
<B>Problem description:<P>
</B><P>
The Iteration subcommittee would like the several iteration proposals to be<P>
writable in portable Common Lisp code. Unfortunately, the only complete<P>
access to hash-tables and packages is through <A REL=DEFINITION HREF="../Body/f_maphas.htm#maphash"><B>MAPHASH</B></A> and <A REL=DEFINITION HREF="../Body/m_do_sym.htm#do-symbols"><B>DO-SYMBOLS</B></A> (and<P>
<A REL=DEFINITION HREF="../Body/m_do_sym.htm#do-external-symbols"><B>DO-EXTERNAL-SYMBOLS</B></A> and <A REL=DEFINITION HREF="../Body/m_do_sym.htm#do-all-symbols"><B>DO-ALL-SYMBOLS</B></A>); none of these existing primitives <P>
is satisfactory for building complex iteration clauses. In particular,<P>
these primitives are fully packaged and do not allow control over the<P>
individual operations of starting the iteration, stopping the iteration,<P>
and advancing to the next step of the iteration.<P>
<P>
<P>
Proposal (<A HREF="iss188.htm">HASH-TABLE-PACKAGE-GENERATORS:ADD-WITH-WRAPPER</A>)<P>
<P>
Add two new macros <A REL=DEFINITION HREF="../Body/m_w_hash.htm#with-hash-table-iterator"><B>WITH-HASH-TABLE-ITERATOR</B></A> and <A REL=DEFINITION HREF="../Body/m_w_pkg_.htm#with-package-iterator"><B>WITH-PACKAGE-ITERATOR</B></A> <P>
to the language as follows:<P>
<P>
<P>
<A REL=DEFINITION HREF="../Body/m_w_hash.htm#with-hash-table-iterator"><B>WITH-HASH-TABLE-ITERATOR</B></A> ((&lt;next-fn&gt; &lt;hash-table&gt;) &amp;body body) [Macro]<P>
<P>
Within the lexical scope of 'body', the name &lt;next-fn&gt; is defined<P>
via <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A> such that successive invocations of (&lt;next-fn&gt;) will <P>
return the items, one by one, from the <A REL=DEFINITION HREF="../Body/t_hash_t.htm#hash-table"><B>hash-table</B></A> which is obtained <P>
by evaluating &lt;hash-table&gt; only once.<P>
<P>
An invocation (&lt;next-fn&gt;) returns three values as follows:<P>
1. a <A REL=DEFINITION HREF="../Body/t_ban.htm#boolean"><B>boolean</B></A> indicating whether an entry is returned (T says yes)<P>
2. the key item (of a &lt;key, value&gt; pair)<P>
3. the value item (of a &lt;key, value&gt; pair)<P>
After all entries have been returned [by successive invocations of<P>
(&lt;next-fn&gt;)], then only one value is returned, namely <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A>.<P>
<P>
<P>
<P>
<A REL=DEFINITION HREF="../Body/m_w_pkg_.htm#with-package-iterator"><B>WITH-PACKAGE-ITERATOR</B></A> ((&lt;next-fn&gt; &lt;package-list&gt; [Macro]<P>
&amp;rest &lt;symbol-types&gt;)<P>
&amp;body body)<P>
<P>
Within the lexical scope of 'body', the name &lt;next-fn&gt; is defined<P>
via <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A> such that successive invocations of (&lt;next-fn&gt;) will <P>
return symbols, one by one, from the packages that are elements<P>
of the list which is obtained by evaluating &lt;package-list&gt; only once. <P>
Each element of &lt;package-list&gt; can be a package or the name of a<P>
package.<P>
<P>
The order of symbols returned does not necessarily reflect the order<P>
of packages in &lt;package-list&gt;. When &lt;package-list&gt; has more than<P>
one element, it is unspecified whether duplicate symbols are<P>
returned once or more than once. Even when &lt;package-list&gt; has only<P>
one element, it is unspecified whether symbols inherited from<P>
multiple packages are returned more than once. See the proposal<P>
DO-SYMBOLS-DUPLICATES:ALLOWED.<P>
<P>
As a convenience, the value of &lt;package-list&gt; can be a package or<P>
the name of a package; this is equivalent to a list of one element.<P>
An argument of <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A> is treated as an empty list of packages.<P>
<P>
The &lt;symbol-types&gt; subform consists of one or more symbols from the<P>
set {:INTERNAL, :EXTERNAL, :INHERITED}. Their order does not<P>
matter. The &lt;symbol-types&gt; subform is not evaluated. This controls<P>
which symbols accessible in a package are returned:<P>
:INTERNAL means the symbols that are present in the package,<P>
but which are not exported;<P>
:EXTERNAL means the symbols that are present and exported;<P>
:INHERITED means the symbols that are exported by used packages<P>
and that are not shadowed.<P>
When more than one argument is supplied for &lt;symbol-types&gt;, then a <P>
symbol is returned if its accessibility matches any one of the <P>
&lt;symbol-types&gt; specified. <A REL=DEFINITION HREF="../Body/m_w_pkg_.htm#with-package-iterator"><B>WITH-PACKAGE-ITERATOR</B></A> signals an error if <P>
no &lt;symbol-types&gt; are specified or if a &lt;symbol-type&gt; not recognized <P>
by the implementation is specified. Implementations are permitted to <P>
extend this syntax by recognizing additional symbol accessibility types.<P>
<P>
An invocation (&lt;next-fn&gt;) returns four values as follows:<P>
1. a <A REL=DEFINITION HREF="../Body/t_ban.htm#boolean"><B>boolean</B></A> indicating whether a symbol is returned (T says yes)<P>
2. a symbol (accessible in one the indicated packages)<P>
3. the accessibility type for that symbol; i.e. one of<P>
:INTERNAL, :EXTERNAL, or :INHERITED<P>
4. the package from which the symbol has been accessed.<P>
After all symbols have been returned [by successive invocations of<P>
(&lt;next-fn&gt;)], then only one value is returned, namely <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>NIL</B></A>.<P>
<P>
The fourth return value is one of the packages present or named in the<P>
&lt;package-list&gt; argument. The meaning of the second, third, and fourth<P>
values is that the returned symbol is accessible in the returned package<P>
in the way indicated by the second return value:<P>
:INTERNAL ==&gt; present, and not exported,<P>
:EXTERNAL ==&gt; present, and exported, <P>
:INHERITED ==&gt; not present (thus not shadowed) but inherited<P>
from some used package.<P>
<P>
It is unspecified what happens if any of the implicit interior state <P>
of an iteration is returned outside the dynamic extent of the WITH-...<P>
form (such as by returning some closure over the invocation form).<P>
<P>
Any number of invocations of <A REL=DEFINITION HREF="../Body/m_w_hash.htm#with-hash-table-iterator"><B>with-hash-table-iterator</B></A> and<P>
<A REL=DEFINITION HREF="../Body/m_w_pkg_.htm#with-package-iterator"><B>with-package-iterator</B></A> can be nested, and the body of the innermost one<P>
can invoke all of the <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A>'<A REL=DEFINITION HREF="../Body/f_ed.htm#ed"><B>ed</B></A> macros, provided all those macros<P>
have distinct names.<P>
<P>
<P>
<B>Examples:<P>
</B><P>
The following function should return T on any <A REL=DEFINITION HREF="../Body/t_hash_t.htm#hash-table"><B>hash-table</B></A>, and signal<P>
an error if the usage of '<A REL=DEFINITION HREF="../Body/m_w_hash.htm#with-hash-table-iterator"><B>with-hash-table-iterator</B></A>' doesn't agree<P>
with the corresponding usage of '<A REL=DEFINITION HREF="../Body/f_maphas.htm#maphash"><B>maphash</B></A>'.<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> test-hash-table-iterator (<A REL=DEFINITION HREF="../Body/t_hash_t.htm#hash-table"><B>hash-table</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((all-entries '())<P>
(generated-entries '())<P>
(unique (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>nil</B></A>)))<P>
(<A REL=DEFINITION HREF="../Body/f_maphas.htm#maphash"><B>maphash</B></A> #'(<A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>lambda</B></A> (key value) (<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>push</B></A> (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> key value) all-entries))<P>
<A REL=DEFINITION HREF="../Body/t_hash_t.htm#hash-table"><B>hash-table</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/m_w_hash.htm#with-hash-table-iterator"><B>with-hash-table-iterator</B></A> (generator-fn <A REL=DEFINITION HREF="../Body/t_hash_t.htm#hash-table"><B>hash-table</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/m_loop.htm#loop"><B>loop</B></A> <P>
;;Note -- this is <A REL=DEFINITION HREF="../Body/s_the.htm#the"><B>the</B></A> &quot;trivial&quot; <A REL=DEFINITION HREF="../Body/m_loop.htm#loop"><B>LOOP</B></A> of CLtL p121<P>
(<A REL=DEFINITION HREF="../Body/m_multip.htm#multiple-value-bind"><B>multiple-value-bind</B></A> (more? key value) (generator-fn)<P>
(<A REL=DEFINITION HREF="../Body/m_when_.htm#unless"><B>unless</B></A> more? (<A REL=DEFINITION HREF="../Body/m_return.htm#return"><B>return</B></A>))<P>
(<A REL=DEFINITION HREF="../Body/m_when_.htm#unless"><B>unless</B></A> (<A REL=DEFINITION HREF="../Body/a_eql.htm#eql"><B>eql</B></A> value (<A REL=DEFINITION HREF="../Body/f_gethas.htm#gethash"><B>gethash</B></A> key <A REL=DEFINITION HREF="../Body/t_hash_t.htm#hash-table"><B>hash-table</B></A> unique))<P>
(<A REL=DEFINITION HREF="../Body/a_error.htm#error"><B>error</B></A> &quot;Key ~S <A REL=DEFINITION HREF="../Body/a_not.htm#not"><B>not</B></A> found for value ~S&quot; key value))<P>
(<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>push</B></A> (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> key value) generated-entries))))<P>
(<A REL=DEFINITION HREF="../Body/m_when_.htm#unless"><B>unless</B></A> (= (<A REL=DEFINITION HREF="../Body/f_length.htm#length"><B>length</B></A> all-entries)<P>
(<A REL=DEFINITION HREF="../Body/f_length.htm#length"><B>length</B></A> generated-entries)<P>
(<A REL=DEFINITION HREF="../Body/f_length.htm#length"><B>length</B></A> (<A REL=DEFINITION HREF="../Body/f_unionc.htm#union"><B>union</B></A> all-entries generated-entries :test #'<A REL=DEFINITION HREF="../Body/f_equal.htm#equal"><B>equal</B></A>)))<P>
(<A REL=DEFINITION HREF="../Body/a_error.htm#error"><B>error</B></A> &quot;Generated entries <A REL=DEFINITION HREF="../Body/a_and.htm#and"><B>and</B></A> Maphash entries don't correspond&quot;))<P>
t))<P>
<P>
<P>
The following function should return T on any package, and signal<P>
an error if the usage of '<A REL=DEFINITION HREF="../Body/m_w_pkg_.htm#with-package-iterator"><B>with-package-iterator</B></A>' doesn't agree<P>
with the corresponding usage of '<A REL=DEFINITION HREF="../Body/m_do_sym.htm#do-symbols"><B>do-symbols</B></A>'.<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> test-package-iterator (<A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/m_when_.htm#unless"><B>unless</B></A> (<A REL=DEFINITION HREF="../Body/f_pkgp.htm#packagep"><B>packagep</B></A> <A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> <A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A> (<A REL=DEFINITION HREF="../Body/f_find_p.htm#find-package"><B>find-package</B></A> <A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A>)))<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((all-entries '())<P>
(generated-entries '()))<P>
(<A REL=DEFINITION HREF="../Body/m_do_sym.htm#do-symbols"><B>do-symbols</B></A> (x <A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A>) <P>
(<A REL=DEFINITION HREF="../Body/m_multip.htm#multiple-value-bind"><B>multiple-value-bind</B></A> (<A REL=DEFINITION HREF="../Body/t_symbol.htm#symbol"><B>symbol</B></A> accessibility) <P>
(<A REL=DEFINITION HREF="../Body/f_find_s.htm#find-symbol"><B>find-symbol</B></A> (<A REL=DEFINITION HREF="../Body/f_symb_2.htm#symbol-name"><B>symbol-name</B></A> x) <A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>push</B></A> (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> <A REL=DEFINITION HREF="../Body/t_symbol.htm#symbol"><B>symbol</B></A> accessibility) all-entries)))<P>
(<A REL=DEFINITION HREF="../Body/m_w_pkg_.htm#with-package-iterator"><B>with-package-iterator</B></A> (generator-fn <A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A> <P>
:internal :external :inherited)<P>
(<A REL=DEFINITION HREF="../Body/m_loop.htm#loop"><B>loop</B></A> <P>
;;Note -- this is <A REL=DEFINITION HREF="../Body/s_the.htm#the"><B>the</B></A> &quot;trivial&quot; <A REL=DEFINITION HREF="../Body/m_loop.htm#loop"><B>LOOP</B></A> of CLtL p121<P>
(<A REL=DEFINITION HREF="../Body/m_multip.htm#multiple-value-bind"><B>multiple-value-bind</B></A> (more? <A REL=DEFINITION HREF="../Body/t_symbol.htm#symbol"><B>symbol</B></A> pkg accessibility)<P>
(generator-fn)<P>
(<A REL=DEFINITION HREF="../Body/m_when_.htm#unless"><B>unless</B></A> more? (<A REL=DEFINITION HREF="../Body/m_return.htm#return"><B>return</B></A>))<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((l (<A REL=DEFINITION HREF="../Body/m_mult_1.htm#multiple-value-list"><B>multiple-value-list</B></A> (<A REL=DEFINITION HREF="../Body/f_find_s.htm#find-symbol"><B>find-symbol</B></A> (<A REL=DEFINITION HREF="../Body/f_symb_2.htm#symbol-name"><B>symbol-name</B></A> <A REL=DEFINITION HREF="../Body/t_symbol.htm#symbol"><B>symbol</B></A>) <P>
<A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A>))))<P>
(<A REL=DEFINITION HREF="../Body/m_when_.htm#unless"><B>unless</B></A> (<A REL=DEFINITION HREF="../Body/f_equal.htm#equal"><B>equal</B></A> l (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> <A REL=DEFINITION HREF="../Body/t_symbol.htm#symbol"><B>symbol</B></A> accessibility))<P>
(<A REL=DEFINITION HREF="../Body/a_error.htm#error"><B>error</B></A> &quot;Symbol ~S <A REL=DEFINITION HREF="../Body/a_not.htm#not"><B>not</B></A> found as ~S in <A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A> ~A [~S]&quot;<P>
<A REL=DEFINITION HREF="../Body/t_symbol.htm#symbol"><B>symbol</B></A> accessibility (<A REL=DEFINITION HREF="../Body/f_pkg_na.htm#package-name"><B>package-name</B></A> <A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A>) l))<P>
(<A REL=DEFINITION HREF="../Body/m_push.htm#push"><B>push</B></A> l generated-entries)))))<P>
(<A REL=DEFINITION HREF="../Body/m_when_.htm#unless"><B>unless</B></A> (<A REL=DEFINITION HREF="../Body/a_and.htm#and"><B>and</B></A> (<A REL=DEFINITION HREF="../Body/f_subset.htm#subsetp"><B>subsetp</B></A> all-entries generated-entries :test #'<A REL=DEFINITION HREF="../Body/f_equal.htm#equal"><B>equal</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/f_subset.htm#subsetp"><B>subsetp</B></A> generated-entries all-entries :test #'<A REL=DEFINITION HREF="../Body/f_equal.htm#equal"><B>equal</B></A>))<P>
(<A REL=DEFINITION HREF="../Body/a_error.htm#error"><B>error</B></A> &quot;Generated entries <A REL=DEFINITION HREF="../Body/a_and.htm#and"><B>and</B></A> Do-Symbols entries don't correspond&quot;))<P>
t))<P>
<P>
<P>
The following function prints out every interned symbol (possibly<P>
more than once):<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> print-all-symbols () <P>
(<A REL=DEFINITION HREF="../Body/m_w_pkg_.htm#with-package-iterator"><B>with-package-iterator</B></A> (next-symbol (<A REL=DEFINITION HREF="../Body/f_list_a.htm#list-all-packages"><B>list-all-packages</B></A>)<P>
:internal :external)<P>
(<A REL=DEFINITION HREF="../Body/m_loop.htm#loop"><B>loop</B></A><P>
;;Note -- this is <A REL=DEFINITION HREF="../Body/s_the.htm#the"><B>the</B></A> &quot;trivial&quot; <A REL=DEFINITION HREF="../Body/m_loop.htm#loop"><B>LOOP</B></A> of CLtL p121<P>
(<A REL=DEFINITION HREF="../Body/m_multip.htm#multiple-value-bind"><B>multiple-value-bind</B></A> (more? <A REL=DEFINITION HREF="../Body/t_symbol.htm#symbol"><B>symbol</B></A>) (next-symbol)<P>
(<A REL=DEFINITION HREF="../Body/s_if.htm#if"><B>if</B></A> more? <P>
(<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#print"><B>print</B></A> <A REL=DEFINITION HREF="../Body/t_symbol.htm#symbol"><B>symbol</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/m_return.htm#return"><B>return</B></A>))))))<P>
<P>
<P>
The following could be an acceptable definition of the function<P>
<A REL=DEFINITION HREF="../Body/f_maphas.htm#maphash"><B>MAPHASH</B></A>, implemented by WITH-HASH-TABLE-ITERATOR&quot;<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> <A REL=DEFINITION HREF="../Body/f_maphas.htm#maphash"><B>maphash</B></A> (<A REL=DEFINITION HREF="../Body/a_fn.htm#function"><B>function</B></A> <A REL=DEFINITION HREF="../Body/t_hash_t.htm#hash-table"><B>hash-table</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/m_w_hash.htm#with-hash-table-iterator"><B>with-hash-table-iterator</B></A> (next-entry <A REL=DEFINITION HREF="../Body/t_hash_t.htm#hash-table"><B>hash-table</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/m_loop.htm#loop"><B>loop</B></A> (<A REL=DEFINITION HREF="../Body/m_multip.htm#multiple-value-bind"><B>multiple-value-bind</B></A> (more key value) (next-entry)<P>
(<A REL=DEFINITION HREF="../Body/m_when_.htm#unless"><B>unless</B></A> more (<A REL=DEFINITION HREF="../Body/m_return.htm#return"><B>return</B></A> <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>nil</B></A>))<P>
(<A REL=DEFINITION HREF="../Body/f_funcal.htm#funcall"><B>funcall</B></A> <A REL=DEFINITION HREF="../Body/a_fn.htm#function"><B>function</B></A> key value)))))<P>
<P>
<P>
<B>Rationale:<P>
</B><P>
The particular way in which hash-tables and packages are represented<P>
need not be standardized, or even exposed to the user. Yet a simpler <P>
handle on them is needed for the various iteration paradigms to be written <P>
in portable code. In fact, after these iterator macros are put into an <P>
implementation, then <A REL=DEFINITION HREF="../Body/f_maphas.htm#maphash"><B>MAPHASH</B></A> and DO-&lt;mumble&gt;-SYMBOLS are trivial usages <P>
of them; but no _efficient_ use of the current primitives will <A REL=DEFINITION HREF="../Body/f_provid.htm#provide"><B>provide</B></A> <P>
the effect of the new macros, namely a form that _returns_ the elements<P>
of a table &quot;one by one&quot;.<P>
<P>
<P>
<B>Current Practice:<P>
</B><P>
Nobody does it this way, but both Symbolics and Lucid are not far off.<P>
<P>
<P>
<B>Cost to Implementors:<P>
</B><P>
Moderate. Possibly a couple day's to a week's work for an implementation <P>
that has to start completely afresh. Something like this is already being<P>
done by the <A REL=DEFINITION HREF="../Body/07_ffb.htm#standard"><B>standard</B></A> package macros [CLtL, p187].<P>
<P>
<P>
<B>Cost to Users:<P>
</B><P>
None.<P>
<P>
<P>
<B>Benefits:<P>
</B><P>
Will <A REL=DEFINITION HREF="../Body/f_provid.htm#provide"><B>provide</B></A> a more basic primitive for iterating over hash-tables and <P>
packages; will permit new iteration paradigms to be written in portable code.<P>
<P>
<P>
<B>Aesthetics:<P>
</B><P>
All other things being equal, it is better to have more general primitives<P>
than less general ones. <P>
<P>
<P>
<B>Discussion:<P>
</B><P>
The Iteration Subcommittee supports this proposal (or, &quot;used to&quot; -- <P>
JonL 6-Oct-88).<P>
<P>
One must be careful not to assume that the invocation (&lt;next-fn&gt;) is a <P>
&quot;generator&quot; function call -- since &lt;next-fn&gt; is <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A>'d in an <P>
implementation dependent way, it could even turn into a special form like<P>
(<A REL=DEFINITION HREF="../Body/s_if.htm#if"><B>if</B></A> something<P>
(<A REL=DEFINITION HREF="../Body/a_values.htm#values"><B>values</B></A> <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>nil</B></A>)<P>
(yet-another-function-call))<P>
<P>
The scoping called for herein may not be quite so useful to the &quot;generators&quot;<P>
style proposals; in particular they offer an interface wherein one may <P>
create a &quot;generator&quot; function of indefinite extent that returns, one-by-one,<P>
the elements of the table. The constrained scoping implicit in these<P>
WITH-... macros is not so much for any kind of optimization, but rather<P>
for coordination of such <A REL=DEFINITION HREF="../Body/t_hash_t.htm#hash-table"><B>hash-table</B></A> &quot;locking&quot; as may occur in multi-<P>
processing implementations like Symbolics. Nevertheless, Dick Waters <P>
thinks these macros should be put in anyway, since it clearly is a <P>
requirement for a portable <A REL=DEFINITION HREF="../Body/m_loop.htm#loop"><B>LOOP</B></A>, and can be use in a limited context <P>
(i.e., not &quot;indefinite scope&quot;) for portable versions of ITERATE and OSS.<P>
<P>
Of course, if an implementation _can_ support an indefinite extent for<P>
a &quot;generator&quot; object returned out of the iterator forms, it is allowed <P>
to do so by this proposal.<P>
<P>
The following macro definitions show how Common Lisp's DO-mumble-SYMBOLS <P>
macros could have been defined in terms of <A REL=DEFINITION HREF="../Body/m_w_pkg_.htm#with-package-iterator"><B>WITH-PACKAGE-ITERATOR</B></A>. They <P>
are intended as illustrative examples, not as new specifications of those <P>
built-in Common Lisp facilities. [PARSE-BODY is as defined in Guy Steele's <P>
&quot;Clarifications&quot; of 6-Dec-85.]<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>defmacro</B></A> <A REL=DEFINITION HREF="../Body/m_do_sym.htm#do-symbols"><B>do-symbols</B></A> ((var <A REL=DEFINITION HREF="../Body/03_da.htm#AMoptional"><B>&amp;optional</B></A> (<A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A> `<A REL=DEFINITION HREF="../Body/v_pkg.htm#STpackageST"><B>*package*</B></A>) result-form)<P>
<A REL=DEFINITION HREF="../Body/03_dd.htm#AMbody"><B>&amp;body</B></A> body <P>
<A REL=DEFINITION HREF="../Body/03_dd.htm#AMenvironment"><B>&amp;environment</B></A> env) <P>
(<A REL=DEFINITION HREF="../Body/m_multip.htm#multiple-value-bind"><B>multiple-value-bind</B></A> (body decls docstring) (parse-body body env)<P>
`(<A REL=DEFINITION HREF="../Body/m_w_pkg_.htm#with-package-iterator"><B>with-package-iterator</B></A> (next-symbol (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> ,<A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A>)<P>
:internal :external :inherited)<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> (more? ,var)<P>
,@decls<P>
(<A REL=DEFINITION HREF="../Body/m_loop.htm#loop"><B>loop</B></A><P>
(<A REL=DEFINITION HREF="../Body/m_when_.htm#unless"><B>unless</B></A> (<A REL=DEFINITION HREF="../Body/m_mult_2.htm#multiple-value-setq"><B>multiple-value-setq</B></A> (more? ,var) (next-symbol))<P>
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> ,var <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>nil</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/m_return.htm#return"><B>return</B></A> ,result-form))<P>
,@body)))))<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>defmacro</B></A> <A REL=DEFINITION HREF="../Body/m_do_sym.htm#do-external-symbols"><B>do-external-symbols</B></A> ((var <A REL=DEFINITION HREF="../Body/03_da.htm#AMoptional"><B>&amp;optional</B></A> (<A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A> `<A REL=DEFINITION HREF="../Body/v_pkg.htm#STpackageST"><B>*package*</B></A>) result-form)<P>
<A REL=DEFINITION HREF="../Body/03_dd.htm#AMbody"><B>&amp;body</B></A> body <P>
<A REL=DEFINITION HREF="../Body/03_dd.htm#AMenvironment"><B>&amp;environment</B></A> env) <P>
(<A REL=DEFINITION HREF="../Body/m_multip.htm#multiple-value-bind"><B>multiple-value-bind</B></A> (body decls docstring) (parse-body body env)<P>
`(<A REL=DEFINITION HREF="../Body/m_w_pkg_.htm#with-package-iterator"><B>with-package-iterator</B></A> (next-symbol (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> ,<A REL=DEFINITION HREF="../Body/t_pkg.htm#package"><B>package</B></A>)<P>
:external)<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> (more? ,var)<P>
,@decls<P>
(<A REL=DEFINITION HREF="../Body/m_loop.htm#loop"><B>loop</B></A><P>
(<A REL=DEFINITION HREF="../Body/m_when_.htm#unless"><B>unless</B></A> (<A REL=DEFINITION HREF="../Body/m_mult_2.htm#multiple-value-setq"><B>multiple-value-setq</B></A> (more? ,var) (next-symbol))<P>
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> ,var <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>nil</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/m_return.htm#return"><B>return</B></A> ,result-form))<P>
,@body)))))<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>defmacro</B></A> <A REL=DEFINITION HREF="../Body/m_do_sym.htm#do-all-symbols"><B>do-all-symbols</B></A> ((var <A REL=DEFINITION HREF="../Body/03_da.htm#AMoptional"><B>&amp;optional</B></A> result-form) <P>
<A REL=DEFINITION HREF="../Body/03_dd.htm#AMbody"><B>&amp;body</B></A> body <P>
<A REL=DEFINITION HREF="../Body/03_dd.htm#AMenvironment"><B>&amp;environment</B></A> env) <P>
(<A REL=DEFINITION HREF="../Body/m_multip.htm#multiple-value-bind"><B>multiple-value-bind</B></A> (body decls docstring) (parse-body body env)<P>
`(<A REL=DEFINITION HREF="../Body/m_w_pkg_.htm#with-package-iterator"><B>with-package-iterator</B></A> (next-symbol (<A REL=DEFINITION HREF="../Body/f_list_a.htm#list-all-packages"><B>list-all-packages</B></A>)<P>
:internal :external)<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> (more? ,var)<P>
,@decls<P>
(<A REL=DEFINITION HREF="../Body/m_loop.htm#loop"><B>loop</B></A><P>
(<A REL=DEFINITION HREF="../Body/m_when_.htm#unless"><B>unless</B></A> (<A REL=DEFINITION HREF="../Body/m_mult_2.htm#multiple-value-setq"><B>multiple-value-setq</B></A> (more? ,var) (next-symbol))<P>
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>setq</B></A> ,var <A REL=DEFINITION HREF="../Body/a_nil.htm#nil"><B>nil</B></A>)<P>
(<A REL=DEFINITION HREF="../Body/m_return.htm#return"><B>return</B></A> ,result-form))<P>
,@body)))))<P>
<P>
-------<P>
&quot;Why not define &lt;next-fn&gt; as a local function as if defined by<P>
<A REL=DEFINITION HREF="../Body/s_flet_.htm#flet"><B>FLET</B></A> rather than a macro as if defined by MACROLET? &quot;<P>
<P>
&quot;A macro gave more scope to the implememtation to optimize<P>
without losing anything essential in these circumstances.&quot;<P>
<P>
</PRE>
<HR>
<A REL=NAVIGATOR HREF="../Front/StartPts.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Starting Points]" SRC="../Graphics/StartPts.gif" ALIGN=Bottom></A><A REL=TOC HREF="../Front/Contents.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Contents]" SRC="../Graphics/Contents.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Master.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Index]" SRC="../Graphics/Index.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Symbol.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Symbols]" SRC="../Graphics/Symbols.gif" ALIGN=Bottom></A><A REL=GLOSSARY HREF="../Body/26_a.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Glossary]" SRC="../Graphics/Glossary.gif" ALIGN=Bottom></A><A HREF="../Front/X3J13Iss.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Issues]" SRC="../Graphics/Issues.gif" ALIGN=Bottom></A><BR>
<A REL=COPYRIGHT HREF="../Front/Help.htm#Legal"><I>Copyright 1996-2005, LispWorks Ltd. All rights reserved.</I></A><P>
</BODY>
</HTML>