[m-dev.] for discussion: stream library v2

Peter Ross peter.ross at miscrit.be
Tue Sep 26 00:43:51 AEDT 2000


On Tue, Sep 26, 2000 at 12:09:32AM +1100, Fergus Henderson wrote:
> On 25-Sep-2000, Peter Ross <peter.ross at miscrit.be> wrote:
> > On Mon, Sep 25, 2000 at 10:49:03AM +1100, Fergus Henderson wrote:
> > > On 24-Sep-2000, Peter Ross <petdr at miscrit.be> wrote:
> > > > Please find attached my second attempt at a stream library.  This time
> > > > I have tried to define a typeclass for an impure lowlevel interface
> > > > for streams, and then defined a pure interface on top of that.
> > > 
> > > I think it's a good idea to build streams using a lowlevel interface
> > > for defining streams with a highlevel interface for using streams
> > > built on top of that, but it would be nicer if the lowlevel interface
> > > didn't need to be impure.
> >
> > I think that the low level interface has to be impure
> 
> Why?
> 
because of the way it is defined. We define the type class method to read
one character as follows

:- impure pred read_char(Handle::in, Char::out) is semidet.

This has to be impure because the implementation may be changing the
external state of the world, it may also not be but we have to assume
the worst.

I for the life of me can think of a way to get around this in a clean
and elegant manner.

> I think a user should be able to define their own stream types without
> having to use any impure code or interfaces.
> 
The users code doesn't have to be impure, but we must assume that the
interface is impure for the reason given above, and so must anyone that
uses the typeclass method.

I honestly can't see a way around this problem, suggestions welcome.


> > > Here you're assuming that if the stream is at eof, then the
> > > previous operation succeeded.  This assumption is not documented
> > > in the lowlevel interface, and I don't think it is likely to hold in
> > > general.  Making this assumption may cause some errors to be ignored.
> > > 
> > You are correct that the assumption needs to be documented.
> > 
> > I arrived at this interface because fgetc return EOF on error or end of
> > file.  So first I check to see whether I am at EOF and if not it must be
> > an error.
> 
> If fgetc() returns EOF, there are three possibilities:
> 
> 	(1) end of file
> 	(2) error
> 	(3) both of the above.  This can happen, for example, if the file
> 	    was at eof, and then fseek() was called, but it failed --
> 	    the failure should be reported, but the file pointer remains
> 	    at eof.
> 
> In case (3), you should return the error, rather than ignoring it and
> returning `eof'.
> 
> In other words, this code is good
> 
> 	int c = fgetc(f);
> 	if (c == EOF) {
> 		if (ferror(f)) {
> 			// handle error
> 		} else {
> 			// handle EOF
> 		}
> 	}
> 
> but the alternative below is bad,
> 
> 	int c = fgetc(f);
> 	if (c == EOF) {
> 		if (feof(f)) {
> 			// handle EOF
> 		} else {
> 			// handle error
> 		}
> 	}
> 
> because it ignores errors in case (3).
> Your code is using the bad alternative.
> 
Understood the idea will make it into version 3.

> > So I guess the next best step would be for me to submit the stream
> > implementation for review with an implementation of stdin/out stream,
> > read file stream and write file stream.
> 
> OK, that sounds good.
> 
Will do then.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list