Reverting changes on backtracking
Posted: 18 Oct 2022 22:26
Hello Thomas,
I am searching for a way of reverting a destructive change on backtracking which is made in a predicate with mode procedure.
This naive try does not work:
However that way it seems to work:
It outputs:
1) initial
2) changed
3) initial
My question now is whether uses of uncheckedConvert like the above are legal in general. Is it always OK to unchecked convert a multi predicate, which has exactly one solution, to a procedure predicate?
Obviously the construction violates the rule that a predicate with mode procedure cannot return with an active backtrack point in it. Maybe above trick to circumvent the rule works out sometimes, but causes problems in other situations. Are there certain restrictions, which when respected, guarantee that the uncheckedConvert will not lead to exceptions or unwanted effects?
I am searching for a way of reverting a destructive change on backtracking which is made in a predicate with mode procedure.
This naive try does not work:
Code: Select all
class facts
state : string := "initial".
class facts
stack : string* := [].
class predicates
changeState : (string Update).
clauses
changeState(Update) :-
stack := [state | stack],
state := Update.
changeState(_Update) :-
[State | RestStack] == stack,
state := State,
stack := RestStack,
fail.
%Raises:
% The predicate 'main::changeState/1 (i)',
% which is declared as 'procedure', is actually 'multi'
clauses
run() :-
stdIO::write("1) ", state, "\n"),
changeState("changed"),
stdIO::write("2) ", state, "\n"),
fail.
run() :-
stdIO::write("3) ", state, "\n").
Code: Select all
class facts
state : string := "initial".
domains
predicate = (string).
class predicates
changeState : (string Update).
clauses
changeState(Update) :-
ChangeState = uncheckedConvert(predicate, changeState_mt),
ChangeState(Update).
class facts
stack : string* := [].
class predicates
changeState_mt : (string Update) multi.
clauses
changeState_mt(Update) :-
stack := [state | stack],
state := Update.
changeState_mt(_Update) :-
[State | RestStack] == stack,
state := State,
stack := RestStack,
fail.
clauses
run() :-
stdIO::write("1) ", state, "\n"),
changeState("changed"),
stdIO::write("2) ", state, "\n"),
fail.
run() :-
stdIO::write("3) ", state, "\n").
1) initial
2) changed
3) initial
My question now is whether uses of uncheckedConvert like the above are legal in general. Is it always OK to unchecked convert a multi predicate, which has exactly one solution, to a procedure predicate?
Obviously the construction violates the rule that a predicate with mode procedure cannot return with an active backtrack point in it. Maybe above trick to circumvent the rule works out sometimes, but causes problems in other situations. Are there certain restrictions, which when respected, guarantee that the uncheckedConvert will not lead to exceptions or unwanted effects?