1
votes

I'm trying to use the -> operator in GNU Prolog, but I'm having some trouble with variable scope. Here's an example:

example(A) :-
  B = A,
  (B == 2 -> write(B), write(' is 2'), nl);
  (write(B), write(' is not 2'), nl).

In the Prolog console:

| ?- example(2).
2 is 2

true ? 

yes
| ?- example(3).
_282 is not 2

yes

When I query example(2), B == 2 succeeds and Prolog knows what the value of B is and thus prints out 2 is 2.

On the other hand, when I query example(3), B == 2 fails and for some reason, Prolog does not know the value of B and therefore prints out some variable _282. I'm very confused as to why Prolog knows the value of B only when B == 2 succeeds. Am I not using the -> operator correctly? Any help would be appreciated.

1

1 Answers

2
votes

You put the semicolon (;) at the wrong place. What you have written is syntactically equivalent to:

example(A) :-
    (   B=A,
        (   B==2
        ->  write(B),
        write(' is 2'),
        nl
        )
    ;   write(B),
        write(' is not 2'),
        nl
    ).

So there are two branches here: one where you set B = A, then check if B == 2, and if that is the case, you write(B) then write(' is 2') followed by a new line. In case B is not 2, you also take that branch, but the calls in the if body (after the ->) will not be called.

Next there is also a completely separate branch where you write(B) but notice that in that branch, we have not first passed through B = A, so for Prolog B is an ungrounded variable, next you write(' is not 2'). But what you thus see with the _282 is an ungrounded variable.

You can fix it by putting the semicolon at the correct place:

example(A) :-
    B = A,
    (  B == 2
    -> (write(B), write(' is 2'), nl)
    ;  (write(B), write(' is not 2'), nl)
    ).

Or less verbose:

example(A) :-
    B = A,
    (  B == 2
    ->  write(B),
        write(' is 2'),
        nl
    ;   write(B),
        write(' is not 2'),
        nl
    )
).

Furthermore it is not clear to me why you construct a new variable in the first place. You can work with A directly:

example(A) :-
    (  A == 2
    ->  write(A),
        write(' is 2'),
        nl
    ;   write(A),
        write(' is not 2'),
        nl
    )
).