[mercury-users] Exceptions and unique modes

Fergus Henderson fjh at cs.mu.OZ.AU
Thu Feb 22 00:21:47 AEDT 2001


On 21-Feb-2001, Peter Ross <peter.ross at miscrit.be> wrote:
> On Fri, Feb 16, 2001 at 02:01:22AM +1100, Fergus Henderson wrote:
> > On 15-Feb-2001, Peter Ross <peter.ross at miscrit.be> wrote:
> > > I am really starting to think that threaded unique objects, should be
> > > treated specially in the language, maybe with some sort of special
> > > syntax which allowed you to use one name to talk about a threaded unique
> > > object and the compiler was smart enough to do a source-to-source
> > > transformation which made this all declarative.
> > 
> > Well, if using one name to talk about a threaded unique object is what
> > you want, I think you may perhaps be able to do it using mutvars
> > (see library/store.m).
> > 
> > It would be nice if we were to provide something similar to that
> > but which works on the io__state rather than a separate store type.
...
> While I think this is a nice idea and the equivalent of IORef in
> Haskell, it faces the problem that we must have an io__state around to
> use it.  This is an unacceptable constraint for me.

OK, so use `store' then!

We can add a cc_multi `try_store', just like `try_io', but for stores.

[Note for implementors: there is one tricky aspect.  If we're not
careful, the user could use `store__extract_ref_value', which destroys
the store and extracts the referenced value without making a copy.
The user could then throw the extracted value, and if the handler gets
both the extracted value and a unique version of the store, then it
can update the reference, which would modify the extracted value,
breaking referential transparency.

In other words, with a naive implementation of `try_store',
the following program

	:- module tricky.
	:- interface.
	:- import_module io.
	:- pred main(io__state::di, io__state::uo) is det.

	:- implementation.
	:- import_module exception, store.

	:- pred tricky(store__ref(T, S), store(S), store(S)).
	:- mode tricky(in, di, uo) is det.

	tricky(Key, Store0, _Store) :-
		store__extract_ref_value(Store0, Key, Value),
		throw(Value).

	main -->
		{ store__new(Store0) },
		{ store__new_ref(Key, "initial", Store0, Store1) },
		{ exception__try_store(tricky(Key), Result, Store1, Store2) },
		print("Result = "), print(Result), nl,
		{ store__set_ref_value(Key, "updated", Store2, _Store) },
		print("Result = "), print(Result), nl.

could print out 

	Result = exception(initial)
	Result = exception(updated)

To avoid this, we need to make a copy of the thrown object before
returning it from try_store.  We already do this in grades which
recover heap automatically on backtracking, but we'll need to do so
even in conservative GC grades.]

> Imagine the following situation:
> 
> :- pred p(list(resource_requests)::in,
>         map(key, resource)::di, map(key, resource)::uo) is det.
> 
> p([], Map, Map).
> p([R | Rs], Map0, Map) :-
>     allocate_resource(R, Resource),
>     get_key(Resource, Key),
>     map__det_insert(Map0, Key, Resource, Map).

`Rs' is a singleton variable.  I think you missed a recursive call
here.  Probably you intended that last line to be

	    map__det_insert(Map0, Key, Resource, Map1),
	    p(Rs, Map1, Map).

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list