Re: [eclipse-clp-users] Attributed variables unification failure within a conditional construct

From: Joachim Schimpf <jschimpf_at_...311...>
Date: Tue, 6 Aug 2024 17:57:04 +0100
On 30/07/2024 15:24, Chris Meudec wrote:
> Hi all,
> I am getting reacquainted with ECLiPSe Prolog after some time with Sicstus, so 
> it appears I am rusty.
> 
> I have used attributed variables extensively in the past, but I am stuck.
> I have defined an attributed variable and have defined a unification handler, 
> but whenever my unification handler fails (as it should)  as part of a condition 
> in a condition construct (*+Condition -> +Then ; +Else*) the entire construct 
> fails rather than executing the Else part.
> 
> I have condensed the problem to a short example below.
> 
> :- module('try').
> :- meta_attribute('try', [unify:unify_name/2]).
> 
> unify_name(_, Attr) :-
>      var(Attr).
> unify_name(Term, Attr) :-
>      compound(Attr),
>      unify_term_name(Term, Attr).
> 
> unify_term_name(_{AttrY}, AttrX) :-
>      -?->
>      AttrX = AttrY.
> 
> try :-
>      add_attribute(X, try('X')),
>      Declarator = X,
>      (Declarator = 2 ->        %when unification fails here as it should, the 
> else part is not executed as expected
>          printf("hello there 10", [])
>      ;
>          printf("hello there 20", [])
>      ).
> try :-
> printf("hello there 30", []).
> 
> I get 30 printed out but I was expecting 20.
> 
> Why? It is rather odd.
> 
> With this attribute, I only want it to succeed when unified with a free variable.
> 
> I could avoid using the conditional construct in such cases but it does not help 
> my understanding and the current behaviour is a little surprising to me.
> 
> Thanks,
> Chris


Hi Chris,

Short answer: as a workaround, insert true/0 after the unification(s) that you 
expect to trigger the failure:

try :-
     add_attribute(X, try('X')),
     Declarator = X,
     (Declarator = 2, true ->          % true/0 forces handlers & waking
         printf("hello there 10", [])
     ;
         printf("hello there 20", [])
     ).



Background: when attributed variables are involved in unifications, the system 
invokes the associated unify-handler(s).  While in principle this should happen 
just after unification, for technical reasons handlers only execute when control 
flow reaches the next "trigger point".  This is typically after a sequence of 
simple goals (such as =/2, simple arithmetic, etc), but before the next regular 
subgoal, e.g.

    ..., X=1, Y=2, Z=3, /*HANDLE X,Y,Z HERE*/ q(...), ...

Unfortunately, owing to a historic design decision for efficiency reasons, cuts 
and -> are classified as simple subgoals.  This means that handlers may 
counter-intuitively slip over and execute _after_ a cut (or a commit to a 
conditional branch as in your example).

As shown above, a dummy subgoal (such as true/0) can always be used to instruct 
the compiler to insert a handler trigger point at an earlier position.

Regards,
Joachim
Received on Tue Aug 06 2024 - 17:16:45 CEST

This archive was generated by hypermail 2.3.0 : Wed Sep 25 2024 - 15:13:21 CEST