[racket] exception instead of EOF?

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Dec 26 17:39:38 EST 2011

Here's another approach, which is to wrap the port with one that raises
an exception before returning an EOF on read or peek:

#lang racket

(define (input-port->error-eof-input-port p [close? #t])
  (define (handle-eof) (error "eof"))
  (define (filter-result r)
     [(eof-object? r) (handle-eof)]
     [(evt? r) (wrap-evt r
                         (lambda (r)
                           (if (eof-object? r)
     [else r]))
   (lambda (bstr r)
     (filter-result r))
   (lambda (bstr offset evt r)
     (filter-result r))

(define p (open-input-bytes #"apple"))
(define p2 (input-port->error-eof-input-port p))
(read-bytes 5 p2) ; ok
(read-byte p2) ; fail

At Mon, 26 Dec 2011 08:06:47 -0800, John Clements wrote:
> On Dec 26, 2011, at 2:46 AM, Dmitry Pavlov wrote:
> > Hello,
> > 
> > I would like to make read-byte and friends to
> > throw an exception in case end of file is
> > reached. That is, when I call read-byte,
> > I know that the byte must be there, otherwise
> > the input data is corrupt. I would prefer
> > not to check the result of every read-byte
> > call. What is the simplest way to achieve
> > such a behavior?
> I would just write a procedure that checks to see a byte is not an eof-object, 
> and signals an error if required. Like this (including test cases):
> #lang racket
> (require rackunit)
> ;; given a stream, reads a byte, signalling 
> ;; an error at the end of the file.
> (define (read-byte/exn input-stream)
>   (define result (read-byte input-stream))
>   (cond [(eof-object? result) 
>          (error 'read-byte/exn "expected byte, got #<eof>")]
>         [else result]))
> (check-equal? (read-byte/exn (open-input-bytes #"ABC")) 65)
> (check-exn exn:fail? 
>            (lambda () (read-byte/exn (open-input-bytes #""))))

Posted on the users mailing list.