<spaecious@gmail.com> wrote:
+---------------
| I'm trying to process each line in a file, and am wondering if there is
| a simpler or more idiomatic way of doing it than the following:
|
| ;;; Simplified version of my real process-line function
| (defun process-line (line)
| (format t "~A~%" line))
|
| ;;; Process stream, calling per-line-fn on each line of the stream
| (defun process (per-line-fn stream)
| (let ((line (read-line stream nil)))
| (if (not (null line))
| (progn (funcall per-line-fn line)
| (process per-line-fn stream)))))
+---------------
This can blow up if your file is large and your CL implementation
doesn't happen to perform tail-call optimization on the tail call
to PROCESS. Note: Common Lisp is not Scheme.
+---------------
| And I kick off the process like so:
|
| CL-USER> (with-open-file (stream "../../words/test.txt")
| (process #'process-line stream))
+---------------
The standard CL idiom omits the intermediate PROCESS function
entirely, and does the whole thing in the WITH-OPEN-FILE call:
(with-open-file (stream "../../words/test.txt")
(loop for line = (read-line stream nil nil)
while line do
(per-line-fn line)))
+---------------
| Is there a simpler way of doing what I'm trying to do here?
+---------------
See above.
+---------------
| I've seen some loop-based solutions, but am staying away from
| loop for the moment.
+---------------
Why?!? It's the most natural way to code this particular task, IMHO.
You don't have to use the entire repertoire of LOOP all at once.
Just pick a few simple idiomatic templates [such as the above]
and add more refinements as you discover you really need them.
Of course, you can also use DO, but to my taste it's a good deal
clunkier:
(with-open-file (stream "../../words/test.txt")
(do ((line #1=(read-line stream nil nil) #1#))
((null line))
(per-line-fn line)))
-Rob
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607