The use is in the thing I told before in
http://discuss.visual-prolog.com/viewtopic.php?t=11882. It is, I am trying to set up an object type, which shall deliver the functionality of the former reference variables. I am following the construction described in your tutorial
http://wiki.visual-prolog.com/index.php ... _a_Project.
A drawback of the tutorial's construction is however, that predicates like
unify/2 have to be declared as
nondeterm rather than
determ. Since backtracking is used to undo the binding of variables, cuts cannot be used anymore in all situations, where it also would cut off a backtrack point to
unify/2.
Thus, when
unify/2 is nondeterm, essential code constructions are unusable. For example
if unify(A, B) then ... else ... end if is unusable, because it cuts off a backtrack point to
unify/2. To code a reference variable version of the function
list::getMember_nd/1-> is not suitable, because enumeration of the list members by backtracking cannot be stopped anymore by a cut.
In short, nondeterminism is a deal-breaker for
unify/2. Some way is needed to make it determ. I proposed a way in
http://discuss.visual-prolog.com/viewtopic.php?t=11882. My trick worked out in a simple example, but unfortunately it relies on some unchecked conversion and turned out to lead to crashes in situations, which are a little more complicated than my example.
I came across another way, to construct a determ
unify/2 predicate: I let
unify/2 push undo-actions on a stack. These undo-actions can be executed later to undo variable bindings. The stack is implemented as a facts database:
Code: Select all
class facts
undoRec : (
programControl::stackMark ApplicableAt,
predicate UndoAction)
nondeterm.
Each call to
unify/2 (and to predicates, in which
unify/2 is used) must be done by a wrapper declared in the fashion:
Code: Select all
predicates
do_dt : (predicate_dt ActionDt)
determ.
clauses
do_dt(ActionDt) :-
StackMark = programControl::getBackTrack(),
(
ActionDt(),
relegateUndoActions(StackMark)
orelse
undoTo(StackMark),
fail
).
It is, instead of calling
unify/2 the usual way as in
I wrap the call in
do_dt/1, so it becomes
Nevertheless the
orelse generates a backtrack point in
do_dt/1 before
ActionDt is called, the predicate
do_dt/0 is determ as well as
ActionDt resp.
unify/2 are.
In case
ActionDt() succeeds,
relegateUndoActions/1 will update the stack marks of the undo records, which
ActionDt has asserted, to further delay execution of the undo actions, and
in case
ActionDt() fails,
undoTo/1 will execute the undo actions.
To wrap calls to predicates, which use reference variable objects and have modes
procedure,
multi,
nondeterm or
failure, I code similar wrapper predicates
do_pr,
do_mt,
do_nd and
do_fl.
In case of an exception, I want to give the reference variable objects the same behavior as ordinary variables have. In detail, if any kind of exception occurs in
Body in
Code: Select all
try
Body
catch Var do
Handler
end try
all bindings made in
Body should be undone through
undoTo/1 before
Handler is executed. For that use I wanted to utilize the user defined runtime exception raiser.
Regards
Martin