[mercury-users] semidet vs unique updating

Nancy Mazur Nancy.Mazur at cs.kuleuven.ac.be
Wed Oct 17 17:17:14 AEST 2001


Hi Michael, 

> > A better solution would be to simply return an extra boolean result
> > indicating success or failure.
> 
> That is:
> 
> :- pred queue__get(queue(T), maybe(T), queue(T)).
> :- mode queue__get(di, uo, uo).
> 
> Quite possible. I've only been kicking and screaming so much because it
> seems that I should be able to mix unique objects with semidet code. The

Although the reuse analysis (also called compile-time garbage collection, 
or update in place, etc) is not yet integrated into the main
branch of the mercury compiler (Pete, whenever you want ;-)), 
what you expect to be able to express can be derived automatically 
by the analysis we've implemented. But even then, using unique objects 
in semidet code can only be allowed and exploited if you're not 
explicitly using that unique object in the else-branch of an if-then-else. 

So the following code can allow the destructive modes without
problem: 
	(
		queue__get(Queue0, Element, Queue)
	-> 
		...
	; 
		% Queue0 is empty, using Queue0 implicitly
		error("Queue is empty")
	)

But in the general case:
	(
		queue__get(Queue0, Element, Queue)
	-> 
		...
	; 
		% using Queue0 explicitly
		do_something(Queue0)
	)
you cannot allow any destructive update in queue__get. (*)
As Ralph pointed out, the problem here lies in the fact that you 
don't know whether failure occurs before or after destructive update. 
So either the compiler takes the safe approach, and sais "nyet", 
or it provides a trailing mechanism to undo the updating. 
Currently the compiler believes the uniqueness-annotations a bit,
but without the full-controlling mechanism provided by a full 
analysis, I think it's quite safe to take the real safe approach, 
and not allowing such semidet-updates. 
But of course, if you think these pieces of code are so
critical to you, then you might consider cheating the compiler, 
but whether that's a good idea on the long run... ? 


Hopefully I'm not answering beside the point, and not
repeating too much what has been said before... ;-)

> declaration above is lying, or at least misleading, in that the queue
> appears to be modified regardless of the outcome, and that if you called
> it enough times it might return yes(T), when it never will, and making it
> semidet would make that point quite clear. And would allow it to be used
> in if statements, dammit.

No point in getting nervous here ;-) 

I just wanted to give my 2 cents too, 
Nancy


(*) I'm lying a bit here, the analysis can do more if you extract the
interesting parts of the queue for the else-branch _before_ the if/then/else. 
E.g. 
	extract(Queue0, SomeSubstructure), 
	(
		queue__get(Queue0, Element, Queue)
	->
		..
 	; 
		do_something(SomeSubstructure)
	). 
As long as the SomeSubstructure is not part of the queue involved in
the destructive update, the analysis will probably be sufficiently 
precise to detect that destructive updates are okay... 

---- my apologies for the chaotic text ;-) 
--------------------------------------------------------------------------
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