shadowtalker
shadowtalker

Reputation: 13893

What error is signaled when READ-LINE hits EOF?

In the Hyperspec, it says:

If an end of file occurs before any characters are read in the line, an error is signaled if eof-error-p is true.

But it doesn't say what error is signaled. I inferred from How to handle end-of-file error when using read-from-string? that the type is END-OF-FILE, but I don't see that actually written in the Hyperspec anywhere. Am I missing something? Is this implementation-dependent?

Upvotes: 2

Views: 498

Answers (2)

Rainer Joswig
Rainer Joswig

Reputation: 139321

Introduction

The behavior of READ-LINE be a bit more complicated: READ-LINE is not a Reader function, but a Streams function in the Specification. A line can be terminated by an EOF. That's not an error for READ-LINE, then. It's only an error when there were no characters in the line, for example when one reads past the EOF, then.

Example file

We have a file without a newline:

CL-USER 2 > (with-open-file (s "/tmp/test.text")
              (loop for c = (read-char s nil nil) while c collect c))
(#\h #\e #\l #\l #\o #\Space #\w #\o #\r #\l #\d)

Reading lines from the example file

Now we call the default READ-LINE on it:

CL-USER 6 > (with-open-file (s "/tmp/test.text")
              (read-line s))
"hello world"
T

Above returns two values: the string read and T indicating that there was no Newline at the end. Thus the end of the file terminated the line. It is not an error.

CL-USER 7 > (with-open-file (s "/tmp/test.text")
              (read-line s t))
"hello world"
T

Even if we say read the line with EOF-ERROR-P = T, we don't get an error.

We get an error, when we read past the EOF:

CL-USER 8 > (with-open-file (s "/tmp/test.text")
              (read-line s t)  ; gets the last line in my file
              (read-line s t))

Error: End of file while reading stream #<STREAM::LATIN-1-FILE-STREAM /tmp/test.text>.
  1 (abort) Return to top loop level 0.

Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.

we can look at the condition object (using LispWorks):

CL-USER 9 : 1 > :cc
#<END-OF-FILE 801009A7C3>

CL-USER 10 : 1 > (describe *)

#<END-OF-FILE 801009A7C3> is an END-OF-FILE
REPORTER-FUNCTION      #<Function 1 subfunction of (SUBFUNCTION LOAD-TIME-VALUE (DEFINE-CONDITION END-OF-FILE)) 80E0615969>
STREAM                 #<STREAM::LATIN-1-FILE-STREAM /tmp/test.text>

CL-USER 11 : 1 > 

READ-LINE in the Spec

I would think that the ANSI Common Lisp specification (-> HyperSpec) simply lacks the usual phrase where it explicitly says what error is signaled. Probably something useful to add in the next revision (if there is ever one).

In CLtL2 all input functions where in one chapter, but the condition system wasn't really integrated into the spec then. In the ANSI CL spec the reader functions are in a later chapter and streams functions are described earlier.

Summary of the READ-LINE behavior

  • first EOF after line contents: no error -> the line is terminated by EOF
  • EOF without prior line contents: error

We can assume that this is an end-of-file error then.

Upvotes: 2

ad absurdum
ad absurdum

Reputation: 21365

The read-line function does return an error of type end-of-file when eof-error-p is true. This is described in the Reader Concepts section of the HyperSpec, 23.1.3.1 The EOF-ERROR-P argument.

Eof-error-p in input function calls controls what happens if input is from a file (or any other input source that has a definite end) and the end of the file is reached. If eof-error-p is true (the default), an error of type end-of-file is signaled at end of file. If it is false, then no error is signaled, and instead the function returns eof-value....

It might be worth noting that, while the read-line entry doesn't explicitly say that the error is of type end-of-file, the HyperSpec entry for read does:

If eof-error-p is true, an error of type end-of-file is signaled at the end of file.

Upvotes: 3

Related Questions