355 lines
30 KiB
HTML
355 lines
30 KiB
HTML
|
<!-- 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 "with" 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> ((<next-fn> <hash-table>) &body body) [Macro]<P>
|
||
|
<P>
|
||
|
Within the lexical scope of 'body', the name <next-fn> is defined<P>
|
||
|
via <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A> such that successive invocations of (<next-fn>) 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 <hash-table> only once.<P>
|
||
|
<P>
|
||
|
An invocation (<next-fn>) 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 <key, value> pair)<P>
|
||
|
3. the value item (of a <key, value> pair)<P>
|
||
|
After all entries have been returned [by successive invocations of<P>
|
||
|
(<next-fn>)], 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> ((<next-fn> <package-list> [Macro]<P>
|
||
|
&rest <symbol-types>)<P>
|
||
|
&body body)<P>
|
||
|
<P>
|
||
|
Within the lexical scope of 'body', the name <next-fn> is defined<P>
|
||
|
via <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A> such that successive invocations of (<next-fn>) will <P>
|
||
|
return symbols, one by one, from the packages that are elements<P>
|
||
|
of the list which is obtained by evaluating <package-list> only once. <P>
|
||
|
Each element of <package-list> 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 <package-list>. When <package-list> has more than<P>
|
||
|
one element, it is unspecified whether duplicate symbols are<P>
|
||
|
returned once or more than once. Even when <package-list> 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 <package-list> 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 <symbol-types> subform consists of one or more symbols from the<P>
|
||
|
set {:INTERNAL, :EXTERNAL, :INHERITED}. Their order does not<P>
|
||
|
matter. The <symbol-types> 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 <symbol-types>, then a <P>
|
||
|
symbol is returned if its accessibility matches any one of the <P>
|
||
|
<symbol-types> 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 <symbol-types> are specified or if a <symbol-type> 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 (<next-fn>) 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>
|
||
|
(<next-fn>)], 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>
|
||
|
<package-list> 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 ==> present, and not exported,<P>
|
||
|
:EXTERNAL ==> present, and exported, <P>
|
||
|
:INHERITED ==> 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> "trivial" <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> "Key ~S <A REL=DEFINITION HREF="../Body/a_not.htm#not"><B>not</B></A> found for value ~S" 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> "Generated entries <A REL=DEFINITION HREF="../Body/a_and.htm#and"><B>and</B></A> Maphash entries don't correspond"))<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> "trivial" <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> "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]"<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> "Generated entries <A REL=DEFINITION HREF="../Body/a_and.htm#and"><B>and</B></A> Do-Symbols entries don't correspond"))<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> "trivial" <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"<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-<mumble>-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 "one by one".<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, "used to" -- <P>
|
||
|
JonL 6-Oct-88).<P>
|
||
|
<P>
|
||
|
One must be careful not to assume that the invocation (<next-fn>) is a <P>
|
||
|
"generator" function call -- since <next-fn> 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 "generators"<P>
|
||
|
style proposals; in particular they offer an interface wherein one may <P>
|
||
|
create a "generator" 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> "locking" 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 "indefinite scope") for portable versions of ITERATE and OSS.<P>
|
||
|
<P>
|
||
|
Of course, if an implementation _can_ support an indefinite extent for<P>
|
||
|
a "generator" 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>
|
||
|
"Clarifications" 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>&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>&body</B></A> body <P>
|
||
|
<A REL=DEFINITION HREF="../Body/03_dd.htm#AMenvironment"><B>&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>&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>&body</B></A> body <P>
|
||
|
<A REL=DEFINITION HREF="../Body/03_dd.htm#AMenvironment"><B>&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>&optional</B></A> result-form) <P>
|
||
|
<A REL=DEFINITION HREF="../Body/03_dd.htm#AMbody"><B>&body</B></A> body <P>
|
||
|
<A REL=DEFINITION HREF="../Body/03_dd.htm#AMenvironment"><B>&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>
|
||
|
"Why not define <next-fn> 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? "<P>
|
||
|
<P>
|
||
|
"A macro gave more scope to the implememtation to optimize<P>
|
||
|
without losing anything essential in these circumstances."<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>
|