[racket] exception instead of EOF?

From: Dmitry Pavlov (dpavlov at ipa.nw.ru)
Date: Tue Dec 27 04:16:45 EST 2011

John, Matthew,

Thanks for your suggestions. I have chosen Matthew's one, as it
seems to be more general. I only had to cancel the peek operation
filtering, as I sometimes use (eof-object? (peek-byte)) to test
for EOF (is there any other way?), so throwing an exception in
that case is not desirable. Here is how it is now:

(filter-read-input-port
    p
    (lambda (bstr r) (filter-result r))
    (lambda (bstr offset evt r) r)
    #t)

Best regards,

Dmitry

On 12/27/2011 02:39 AM, Matthew Flatt wrote:
> 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)
>      (cond
>       [(eof-object? r) (handle-eof)]
>       [(evt? r) (wrap-evt r
>                           (lambda (r)
>                             (if (eof-object? r)
>                                 (handle-eof)
>                                 r)))]
>       [else r]))
>    (filter-read-input-port
>     p
>     (lambda (bstr r)
>       (filter-result r))
>     (lambda (bstr offset evt r)
>       (filter-result r))
>     close?))
>
> (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.