Subject: Re: Stupid looping question
From: (Rob Warnock)
Date: Fri, 05 Sep 2003 08:21:50 -0500
Newsgroups: comp.lang.lisp
Message-ID: <>
Jonathan.Bailleul <> 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)))


[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		<>
627 26th Avenue			<URL:>
San Mateo, CA 94403		(650)572-2607