users-prolog
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Gprolog member/2 error ?!


From: Nicolas Pelletier
Subject: Re: Gprolog member/2 error ?!
Date: Tue, 24 Aug 2010 21:08:11 +0900

Hello,

On Mon, Aug 23, 2010 at 01:32, Pedro Fialho <address@hidden> wrote:
> Hi all,
>
> I found a strange error on my gprolog coding, namely on the source:
>
> pred1([R-C-P|Ls], [R-C-P|Ls1]):-
>    memberchk(rel(_,X,Y), C),
>    memberchk(rel(_,Y,_), C),
>    nth(1,P,Z),
>    ...
[snip!]
>  Also tried with member/2 but the List is always changed on exit of the
>  secound call to member/2. Notice the rel(de,_198617,_198661) predicate
>  is changed to rel(de,_198617,_198617) although member/2 is not stated
>  as a destructive process.

memberchk/2 and member/2 are not destructive, but they will still try
to unify their first argument with an element of the list. This
unification will result in variables being shared, which is what you
are seeing here. The following, simpler, example also shows
unification happening:

bash-4.1$ gprolog
GNU Prolog 1.3.0
By Daniel Diaz
Copyright (C) 1999-2007 Daniel Diaz
| ?- [user].
compiling user for byte code...
p(X, Y, L) :-
    memberchk(rel(_,X,Y), L),
    memberchk(rel(_,Y,_), L).

user compiled, 4 lines read - 648 bytes written, 26169 ms

yes
| ?- trace, p(X, Y, [rel(A, B, C)]).
The debugger will first creep -- showing everything (trace)
      1    1  Call: p(_16,_17,[rel(_18,_19,_20)]) ?
      2    2  Call: memberchk(rel(_93,_16,_17),[rel(_18,_19,_20)]) ?
      2    2  Exit: memberchk(rel(_18,_16,_17),[rel(_18,_16,_17)]) ?
      3    2  Call: memberchk(rel(_122,_17,_124),[rel(_18,_16,_17)]) ?
      3    2  Exit: memberchk(rel(_18,_16,_16),[rel(_18,_16,_16)]) ?
      1    1  Exit: p(_16,_16,[rel(_18,_16,_16)]) ?

C = B
X = B
Y = B

yes
{trace}
| ?-

To prevent unification from happening in the second memberchk/2, you
need to undo the substitution performed during unification with a
double negation:

| ?- [user].
compiling user for byte code...
p(X, Y, L) :-
    memberchk(rel(_,X,Y), L),
    \+ \+ memberchk(rel(_,Y,_), L).

user compiled, 4 lines read - 742 bytes written, 28446 ms

yes
| ?- trace, p(X, Y, [rel(A, B, C)]).
The debugger will first creep -- showing everything (trace)
      1    1  Call: p(_16,_17,[rel(_18,_19,_20)]) ?
      2    2  Call: memberchk(rel(_93,_16,_17),[rel(_18,_19,_20)]) ?
      2    2  Exit: memberchk(rel(_18,_16,_17),[rel(_18,_16,_17)]) ?
      3    2  Call: \+ \+memberchk(rel(_122,_17,_124),[rel(_18,_16,_17)]) ?
      4    3  Call: \+memberchk(rel(_122,_17,_124),[rel(_18,_16,_17)]) ?
      5    4  Call: memberchk(rel(_122,_17,_124),[rel(_18,_16,_17)]) ?
      5    4  Exit: memberchk(rel(_18,_16,_16),[rel(_18,_16,_16)]) ?
      4    3  Fail: \+memberchk(rel(_122,_17,_124),[rel(_18,_16,_17)]) ?
      3    2  Exit: \+ \+memberchk(rel(_122,_17,_124),[rel(_18,_16,_17)]) ?
      1    1  Exit: p(_16,_17,[rel(_18,_16,_17)]) ?

X = B
Y = C

yes

Note this is an intrinsic property of the unification algorithm, and
as such, present in all Prologs. In other words, you will have to take
into account which variables you wish to unify, and when, if going
this route. If not, you might want to investigate using dynamic
predicates to store partially instantiated data you want to keep (e.g.
assert and retract).

Hope this helps,

-- 
Nicolas



reply via email to

[Prev in Thread] Current Thread [Next in Thread]