Subject: Re: How can "cons per call" be so different for these two very similar functions?
From: rpw3@rpw3.org (Rob Warnock)
Date: Sat, 02 Sep 2006 20:46:55 -0500
Newsgroups: comp.lang.lisp
Message-ID: <GsGdnW4beKGSqWfZnZ2dnUVZ_q6dnZ2d@speakeasy.net>
dpapathanasiou <denis.papathanasiou@gmail.com> wrote:
+---------------
| > (defun split-on-corpus (atoms preprocessed-corpus)
| >   (loop :for atom :in atoms
| >         :if (gethash atom preprocessed-corpus)
| >               :collect atom :into present
| >         :else :collect atom :into absent
| >         :finally (return (list present absent))))
| 
| Thanks for posting this; despite reading Seibel's chapter on "loop",
| I've been avoiding its use in favor of primitive iterators.
+---------------

Pascal's point about using multiple results to avoid doing
the work twice was completely independent of using the LOOP
macro per se. One could do it just as easily with DOLIST, say:

    (defun split-on-corpus (atoms preprocessed-corpus)
      (let (present absent)
	(dolist (atom atoms (list (reverse present) (reverse absent)))
	  (if (gethash atom preprocessed-corpus)
	    (push atom present)
	    (push atom absent)))))

or even [somewhat less cleanly] with plain ol' DO:

    (defun split-on-corpus (atoms preprocessed-corpus)
      (do ((atoms atoms (cdr atoms))
	   (atom (car atoms) (car atoms))
	   (present)
	   (absent))
	  ((null atoms) (list (reverse present) (reverse absent)))
	(if (gethash atom preprocessed-corpus)
	  (push atom present)
	  (push atom absent))))

The main advantage to the LOOP version is that it [probably]
uses an internal cached tail pointer to implement the COLLECTs,
so the two sub-results don't need to be REVERSE'd. One could
of course do that with DOLIST/DO as well, but learning to use
LOOP/COLLECT is far simpler!  ;-}


-Rob

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