[m-dev.] for review: stream I/O

Fergus Henderson fjh at cs.mu.OZ.AU
Tue Oct 3 12:01:33 AEDT 2000


On 02-Oct-2000, Ralph Becket <rbeck at microsoft.com> wrote:
> >From Michael Day on 02/10/2000 13:49:26
> > 
> > I
> > considered a number of wrapper predicates that take an io__state pair as
> > well as a stream pair to enforce total ordering for those cases when you
> > really need it, I assume that wouldn't be too hard to add.
> 
> I may not have access to the io__state where I want this behaviour; the
> idea of having to pass in the io__state whenever I just want a total order
> on the operations of some non-io streams seems something of a hack to me.

The only time enforcing a total order on the operations of different
streams makes any sense is when the streams in question have some
shared state.  For non-io streams, I suspect that is a fairly rare
case.  However, I guess it would make sense to allow user-defined
streams which use `store__store' or something like that rather than
`io__state'.  This would mean that you'd need a multi-parameter
type class: one parameter would be the stream handle type, and
the other parameter would be the stream state type.

> > <looks blank, searches for meaning of conflated in nearby dictionary>
> 
> Conflate: to combine two or more things into a whole.
> 
> As I understand it, what is currently being proposed conflates the 
> following two ideas:
> 1. the state object being manipulated; and
> 2. a parameter (`handle') indicating how a particular operation should 
> affect a state object.
> 
> In many cases, the handle parameter is left implicit (e.g. the current io
> library writes to stdout and reads from stdin by default).
> 
> As I see it, for a state object to be a stream, it has to have (one of)
> read_char/3 and write_char/3 as methods with a default `handle' (actually
> I probably want a whole host of other methods as standard with a library
> providing default implementations.)
> 
> For io__states this is straightforward and one can set up the `handle'
> with io__see/seen/tell/told.  Forking off separate IO streams from the
> io__state is going to cause trouble (e.g. cc_multi's all over the shop.)
> 
> Also, I don't see why I need to involve the io__state when I'm setting up,
> say, a string stream.
> 
> So this is mainly a criticism of the stream.m module, or rather
> stream__init/4.  stream.m provides (a) a means of adding a putback buffer
> to a stream and (b) some handy predicates over streams.
> 
> (a) is a bit arbitrary - e.g. what about seekable streams?  I would rather
> see the interface changed to include
> 
> :- typeclass putback_stream(S) <= input_stream(S) where [
> 	pred putback_char(char::in, S::di, S::uo) is det
> ].
> 
> and do away with stream__putback_char/3.
> 
> One could then provide a convenience wrapper type
> 
> :- type putback_stream(S) == {list(char), S}.
> 
> :- instance putback_stream(putback_stream(S)) where [
> 	putback_char(Char, {Chars, Strm}, {[Char | Chars], Strm})
> ].
> :- instance input_stream(putback_stream(S)) <= input_stream(S) where [
> 	( read_char(Result, {Chars0, Strm0}, {Chars, Strm}) :-
> 		(	Chars0 = [Char | Chars],
> 			Result = ok(Char),
> 			Strm   = Strm0
> 		;
> 			Chars0 = [],
> 			Chars  = [],
> 			read_char(Result, Strm0, Strm)
> 		)
> 	)
> ].
> 
> The other predicates in stream.m aren't really stream__stream 
> specific.

I agree with all of the above.

> As I say, I'd rather have an higher level stream abstraction which
> included stuff like read_word/line, ignore_whitespace etc. as
> methods since (a) we're going to provide default method implementations
> RSN (so I'm told (except for the RSN bit :)) and (b) a stream
> implementation should be free to use more efficient methods than the
> default implementations (e.g. clever buffering & read-ahead).

Well, I think for now we should probably keep things simple --
the design problem seems hard enough already ;-)
If/when we add support for default methods, we can make some of
the higher level procedures as methods to the existing type classes.

One procedure which is definitely worth optimizing in this fashion
is read_file_as_string (or read_stream_as_string, or whatever we
call the stream version).  But for read_word/line, ignore_whitespace,
etc., I'd just make them ordinary procedures rather than class methods,
at least in the short term.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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