9

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.

Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
Fredrick Pennachi
  • 832
  • 1
  • 8
  • 17

2 Answers2

15

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 ... )
Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
12

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 and EOF-VALUE specify what happens when your program makes an attempt to read from an exhausted stream. If EOF-ERROR-P is true (the default), then Lisp will signal an error upon an attempt to read an exhausted stream. If EOF-ERROR-P is NIL, then Lisp returns EOF-VALUE (default NIL) instead of signalling an error.

You can use this as a simple termination condition for your function.

Gustav Bertram
  • 14,591
  • 3
  • 40
  • 65
ire_and_curses
  • 68,372
  • 23
  • 116
  • 141
  • 1
    @GustavBertram Not sure what you mean. It is still available for download from the link I posted over seven years ago in this answer. I just confirmed. – ire_and_curses Feb 02 '17 at 22:05