Subject: Re: Stupid looping question
From: rpw3@rpw3.org (Rob Warnock)
Date: Fri, 05 Sep 2003 08:21:50 -0500
Newsgroups: comp.lang.lisp
Message-ID: <2rOdne0RDthzEMWiXTWc-g@speakeasy.net>
Jonathan.Bailleul <bailleul@greyc.ismra.fr> wrote:
+---------------
| The do* formulation appeared first, but it becomes awkward since I have
| to supply the same (long) expression for variable initialisation and
| update.
...
|   (with-open-file (stream (make-pathname :name input-file-name)
|			    :direction :input)
|     (let ((acc (list)))
|       (do* ((current-line (read-line stream nil 'eof)
| 			  (read-line stream nil 'eof)))
| 	  ((equal current-line 'eof) (nreverse acc))
| 	(push (str-tokenize current-line) acc)))))
+---------------

Others have shown you the standard idioms using LOOP, so I won't,
but will make a few small observations:

- You don't need DO* here; DO is enough.
- You don't need a separate LET; DO is enough.
- You don't need to call LIST to get an empty list; a constant will do.
- Since your EOF object is a symbol, your don't need EQUAL; EQ is enough.
- An idiom useful especially with DO[1] is to use #= & ## syntax when
   repeating an long form.

Putting it all together, we get:

      (with-open-file (stream input-file-name)
	(do ((acc '())
	     (line #1=(read-line stream nil 'eof) #1#))
	    ((eq line 'eof) (nreverse acc))
	  (push (str-tokenize line) acc)))


-Rob

[1] Note: This is not needed with LOOP's "for var = form", since it's
    already implied. That is, "for var = form" has the same meaning as
    "for var = #1=form then #1#".]

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