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

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


On 02-Oct-2000, Peter Ross <petdr at miscrit.be> wrote:
> On Mon, Oct 02, 2000 at 07:08:20PM +1100, Fergus Henderson wrote:
> > On 01-Oct-2000, Peter Ross <petdr at miscrit.be> wrote:
> > > +	% Given a handle to a stream construct a unique stream object
> > > +	% which can be used to do IO on the stream.
> > > +	% This object initialises its state from the io__state.
> > > +:- pred stream__init(S::in, stream(S)::uo, io__state::di, io__state::uo) is det.
> > > +
> > > +	% Tie the stream back into the io__state.  Omitting this call
> > > +	% may allow the compiler to optimize away the stream I/O.
> > > +:- pred stream__destroy(stream(S)::di, io__state::di, io__state::uo) is det.
> > 
> > There are some nasty semantic problems with these routines.
> > At very least, the documentation is incomplete.
> > More likely the interface declared here won't work (i.e. can't be
> > implemented in a way that is logically sound and that matches
> > their intended semantics).
> > 
> > The comment for `stream__destroy' explains its purpose, but
> > doesn't describe its effect.  What are the declarative and
> > operational semantics of `stream__destroy'?
> > 
> > In the case where there is no call to stream__destroy, the logically
> > correct behaviour is for there to be no side effects, [...]
>
> I understand the problem that you are pointing out here, and I would
> appreciate a possible solution.

Well, one possible approach is the one that I mentioned earlier:
instead of providing stream__init and stream__destroy,
provide `with_stream', which would be equivalent to

	:- mode with_stream(in, pred(di, uo) is det, di, uo) is det.
	with_stream(S0, Pred) -->
		stream__init(S0, Stream0),
		{ Pred(Stream0, Stream) },
		stream__destroy(Stream).

The difference is that now it is not possible to have
any unmatched calls to stream__destroy.  (The only exception
is the case when an exception is thrown, but since the final io__state
after try_io is unspecified, it doesn't matter what I/O the
implementation does in that case.)

However, that approach might limit expressiveness too much -- I'm not sure.
The with_stream/4 that I defined above doesn't let the predicate
have any output, except via side effects to the io__state.
So probably you want something like

	:- mode with_stream(pred(out, di, uo) is det, out, di, uo) is det.
	with_stream(Pred, Result, S0, S) -->
		stream__init(S0, Stream0),
		{ Pred(Result, Stream0, Stream) },
		stream__destroy(Stream, S).

instead.

> The only solution that I can think of is to have two stream type
> classes, one which is side effect free and one which isn't.
> Here is the interface for the side effect streams.
> 
> :- typeclass stream__input(S) where [
>     pred stream__read_char(S, stream__result(char), io__state, io__state)
>     mode stream__read_char(in, out, di, uo) is det
> ].
> 
> where S must be a handle which is used to select the correct read
> character implementation.

That would work too.  It depends on what you're trying to achieve.
That is a less ambitious design, more similar to the existing I/O
library; it just adds the possibility of user-defined stream types
(at the Mercury level) and provides genericity over the different
stream types.  The other alternatives that we're discussing are
more radical changes: by splitting the io__state into sub-states
for different streams, they allow more parallelism/concurrency, and
are arguably a more elegant design, but this comes at a cost of
increased complexity (e.g. the need to lock files, for the
deterministic parallelism case, or the unspecified order of
side effects, for the `cc_multi' concurrent case.).

These approaches don't have to be mutually exclusive, of course.
There may be a case for providing all three:
	- one to use when you care about the order of side effects
	- one to use when you don't care about the order of side
	  effects, even though they may influence the result
	- one to use when you know that the order of side effects
	  won't influence the result

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