Subject: Re: Excerise in Graham's ANSI Common Lisp
From: rpw3@rpw3.org (Rob Warnock)
Date: Wed, 19 Jul 2006 04:48:37 -0500
Newsgroups: comp.lang.lisp
Message-ID: <ntudnbd-cutoYiDZnZ2dnUVZ_qidnZ2d@speakeasy.net>
Sacha <no@address.spam> wrote:
+---------------
| "Joe Foran" <usenetjf@gmail.com> wrote in message 
| > Eric Hanchrow wrote:
| >> You're misusing "append", in typical newbie fashion :-)
| >> Try this:
...
| >> The only difference is that I'm calling "setf" on the result of "append".
| 
| This algorithm will have very bad performances for a big hash-table as the 
| append function will need to run down the association list on each 
| iteration.  I would use the loop facility, collecting the conses, or even 
| better just push the cons on the list as the order is not important (coming 
| from a hash-table anyways).
+---------------

Indeed. Here's my own personal convenience function for this:

    (defun hash-table-alist (table &key (test (constantly t)))
      (let (result)
	(do-hash (key value table result)
	  (when (funcall test key value)
	    (push (cons key value) result)))))

In OP's case, he might not need the generality of the :TEST keyword, so:

    (defun hash-table-alist (table)
      (let (result)
	(do-hash (key value table result)
	  (push (cons key value) result))))

One can also do it with LOOP [albeit with a somewhat awkward syntax]
this way:

    (defun hash-table-alist (table)
      (loop for key being the hash-keys in table
		using (hash-value value)
	collect (cons key value)))


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607