Reputation: 842
How do I read an input stream until EOF in Lisp? In C, you might do it like this:
while ((c = getchar()) != EOF)
{
// Loop body...
}
I would like to be able to pipe data to my Lisp programs without having to specify the data size in advance. Here's an example from something I'm doing now:
(dotimes (i *n*)
(setf *t* (parse-integer (read-line) :junk-allowed T))
(if (= (mod *t* *k*) 0) (incf *count*)))
In this loop, the variable *n*
specifies the number of lines I'm piping to the program (the value is read from the first line of input), but I would like to just process an arbitrary and unknown number of lines, stopping when it reaches the end of the stream.
Upvotes: 10
Views: 10308
Reputation: 70220
read-line
takes an optional argument (eof-error-p
) allowing it to return either NIL
(default) or a user-specified value (eof-value
) on hitting an EOF
, instead of signalling an error.
From Chapter 19 of Successful Lisp:
READ-LINE &optional stream eof-error-p eof-value recursive-p
In the read functions listed above, optional arguments
EOF-ERROR-P
andEOF-VALUE
specify what happens when your program makes an attempt to read from an exhausted stream. IfEOF-ERROR-P
is true (the default), then Lisp will signal an error upon an attempt to read an exhausted stream. IfEOF-ERROR-P
is NIL, then Lisp returnsEOF-VALUE
(defaultNIL
) instead of signalling an error.
You can use this as a simple termination condition for your function.
Upvotes: 12
Reputation: 139321
See the HyperSpec for READ-LINE
(loop for line = (read-line stream nil :eof) ; stream, no error, :eof value
until (eq line :eof)
do ... )
or sometimes with nil
(loop for line = (read-line stream nil nil)
while line
do ... )
Upvotes: 15