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

Ralph Becket rbeck at microsoft.com
Tue Oct 3 01:00:10 AEDT 2000


>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.

> <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.

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).

Ralph

--------------------------------------------------------------------------
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