Re: freeze/2 and nb_setarg/3 interaction

Jan Wielemaker <[email protected]> Mon, 14 Apr 2014 22:23:24 +0200
Newsgroups gmane.comp.ai.prolog.swi
Message-ID <[email protected]>
On 14-04-14 22:13, Michael Hendricks wrote:
> Thanks Michael.  That example and thread pointed me in a helpful direction.
>  This seems to be because the unification "H=a" is still trailed.  On
> backtracking that unification is undone which makes H unbound again.
> 
> I've modified your broken2 example by adding an extra choicepoint to make
> this apparent:
> 
> broken3 :-
>     X = [H|_],
>     (   H = a,
>         (nb_setarg(1, X, b); true),
>         writeln(X),
>         fail
>     ;   writeln(X)
>     ).
> 
> ?- broken3.
> [b|_G1940]
> [b|_G1940]
> [_G1939|_G1940]
> true.

Never realised that.  So, the sequence of unifying a variable argument
of a compound and then using nb_setarg/3 undoes all bindings on backtracking
to before the unification.  The same will happen for setarg/3 followed by
nb_setarg/3.

I guess that is something that just needs to be documented.  It is unclear
what the `right' action is in the first place (after all, the unification
or backtrackable assignment assumes the old state is restored on
backtracking).

Even if we would like the nb_* version to be permanent, there is no
realistic
way to implement that: the nb_* predicate would have to analyse the
trail and
choicepoints to see whether there is any trailing on that location after the
term was created.

	Cheers --- Jan