There is a very detailed Draft proposal for setup_call_cleanup/3.
Let me quote the relevant part for my question:
c) The cleanup handler is called exactly once; no later than upon failure of G. Earlier moments are:
If G is true or false, C is called at an implementation dependent moment after the last solution and after the last observable effect of G.
And this example:
setup_call_cleanup(S=1,G=2,write(S+G)).
Succeeds, unifying S = 1, G = 2.
Either: outputs '1+2'
Or: outputs on backtracking '1+_' prior to failure.
Or (?): outputs on backtracking '1+2' prior to failure.
In my understanding, this is basically because a unification is a backtrackable goal; it simply fails on reexecution. Therefore, it is up to the implementation to decide whether to call the cleanup just after the fist execution (because there will be no more observable effects of the goal), or postpone until the second execution of the goal which now fails.
So it seems to me that this cannot be used to detect determinism
portably. Only a few built-in constructs like true
, fail
, !
etc. are genuinely non-backtrackable.
Is there any other way to check determinism without executing a goal twice?
I'm currently using SWI-prolog's deterministic/1
, but I'd certainly
appreciate portability.
X=2
is deterministic on the top level. – mnish