[mercury-users] Unique mode questions

Fergus Henderson fjh at cs.mu.OZ.AU
Fri Apr 20 14:03:01 AEST 2001


On 19-Apr-2001, Terrence Brannon <princepawn at earthlink.net> wrote:
> In looking at this section of the manual I developed the following
> questions:
> 
> 1- The manual states:
> 
>  Mercury also provides "unique" insts `unique' and `unique(...)' which
>  are like `ground' and `bound(...)' respectively, except that they
>  carry the additional constraint that there can only be one reference
>  to the corresponding value.
> 
> So my question is, what is meant by one reference to a value? Does
> that mean I cannot access the memory contents more than once?

It means that you can't have more than one variable
which refers to that value live at the same time.

> For example, here is a predicate with a unique-out variable:
> 
> :- pred string__length(string, int).
> :- mode string__length(in, uo) is det.
> 
> it is wrong for me to do the following:
> 
> string__length(S,L), use_it_once(L), use_it_again(L).

That depends on what the modes for `use_it_once' and `use_it_again' are.
If `use_it_once' has a `di' mode (unique >> dead), then that would not
be allowed.  But that example would be OK if `use_it_once' has a `ui'
mode (unique >> unique).  (However, `ui' modes are not properly supported
in the current implementation.)

Here's another example which would not be allowed:

	:- mode use_it_twice(di, di).

	p :-
		string__length(S,L),
		use_it_twice(L, L).
	
> 2- Continuing, the manual states:
> 
>  There is also an inst `dead' which means that there are no references
>  to the corresponding value, so the compiler is free to generate code
>  that reuses that value. 
> 
> Now the obvious question is: why would a dead value exist in the first
> place?!

Well, it can start off live, and then later become dead.

> And the neophyte's intuitive explanation would be:
> 
> :- pred list__length_2(list(T), int, int).
> :- mode list__length_2(in, in, out) is det.
> 
> list__length_2([], N, N).
> list__length_2([_ | L1], N0, N) :-
> 	N1 is N0 + 1,
> 	list__length_2(L1, N1, N).
> 
> 
> ... the _ above is a case where the mode could have been dead but
> unfortunately the tail of the list was needed. So then the question
> remains, why pass something that isn't going to be used? It doesn't
> make much sense to have a mode like this in my eyes.

list__length_2 is not a good example for the use of unique modes.
But you could use a `di' mode for the first argument:

	:- mode list__length_2(di, in, out) is det.

This would mean that after the call to list__length_2, the first argument
is dead, i.e. will no longer be used.  The compiler could use this information
to do "compile-time garbage collection", i.e. inserting explicit calls to
free() or the equivalent to deallocate the memory for the list cons cells.

If you then write e.g.

	:- func num_prime_factors(int) = int.
	num_prime_factors(N) = Len :-
		PrimeFactorsList = get_prime_factors(N),
		list__length_2(PrimeFactorsList, 0, Len).

	:- func get_prime_factors(int) = list(int).
	:- mode get_prime_factors(in) = uo is det.
	get_prime_factors(N) = ...

then `PrimeFactorsList' is live before the call to list__length_2, but dead
afterwards, so it would be OK for this call to list__length_2 to use the `di'
mode of list__length_2.

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