I am confused about how conditionals are used in prolog. While Example 1 is the case for a conditional, Example 2 shows a case where it says NewPos = Exit
on the other side of the ->
operator. Is it checking if NewPos
is equal to Exit
or is it the case that the value Exit
is being assigned to NewPos
? Shouldn't an is
be used to assign values in prolog?
Sorry if this is a very basic syntax question.
Example 1
Current = b(_,Cost,NewPos),
( Exit=none -> backtrack_path(Current,Visited,RPath)
; Exit=b(5,5) -> backtrack_path(Current,Visited,RPath)
Example 2
Current = b(_,Cost,NewPos),
( Exit=none -> backtrack_path(Current,Visited,RPath)
; otherwise -> NewPos = Exit,
backtrack_path(Current,Visited,RPath)
For a more detailed look at the Prolog ->
operator, see What's the meaning of Prolog operator '->'. Your examples are covered below.
Example 1:
Current = b(_,Cost,NewPos),
Unifies Current
with the term, b(_, Cost, NewPos)
. Unficiation in Prolog is not the same as assignment. In unification, Prolog will attempt to match the two arguments of =/2
possibly instantiating variables on either side to achieve the unification. If, for example, Current
, Cost
and NewPos
are all uninstantiated, then Current
will be instantiated with b(_, Cost, NewPos)
(using the same variables, Cost
and NewPos
. If, later on, Cost
is instantiated with, say, 10
, then Current
will also become, b(_, 10, NewPos)
, in effect.
( Exit=none -> backtrack_path(Current,Visited,RPath)
; Exit=b(5,5) -> backtrack_path(Current,Visited,RPath)
;
has lower precedence than ->
, so this is, in effect:
( Exit=none
-> backtrack_path(Current,Visited,RPath)
; ( Exit=b(5,5)
-> backtrack_path(Current,Visited,RPath),
...
),
...
)
Exit = none
will attempt to unify Exit
and the atom, none
. It will succeed if Exit
is uninstantiated (and will then instantiate Exit
with none
), or can succeed if Exit
is already instantiated as none
. It will fail if Exit
is instantiated with any term that doesn't match none
.
If Exit = none
succeeds, then the first backtrack_path(Current, Visited, RPath)
is called. If it fails, then an attempt is made to unify Exit
with b(5,5)
. If the prior Exit = none
failed, then we got to this point because Exit
was already unified with something that didn't match none
, and it will succeed Exit = b(5,5)
only if it was already unified with a term that looks like, b(X, Y)
. Otherwise, it will also fail. If it succeeds, then, again, backtrack_path(Current, Visited, RPath)
will be called.
Example 2:
Current = b(_,Cost,NewPos),
( Exit=none -> backtrack_path(Current,Visited,RPath)
; otherwise -> NewPos = Exit,
backtrack_path(Current,Visited,RPath)
,
has highest precedence, followed by ->
, followed by ;
. So this is effectively:
Current = b(_,Cost,NewPos),
( Exit=none
-> backtrack_path(Current,Visited,RPath)
; ( otherwise
-> ( NewPos = Exit,
backtrack_path(Current,Visited,RPath),
...
),
...
),
...
)
See the discussion above about unification. If Exit = none
succeeds, then backtrack_path(Current, Visited, RPath)
is called. Otherwise, then then otherwise
call is done (NOTE that if otherwise
is a block of code, then operator precedence can affect the grouping I show above, so I'm assuming otherwise
is a block which has precedence over the following ->
).
If otherwise
succeeds, then Prolog attempts NewPos = Exit
, and if that succeeds, it will move on to call, backtrack_path(Current, Visited, RPath)
. If the NewPos = Exit
unification fails, then, in this case, lacking an "else" or "OR" (;
) type of expression, it might backtrack all the way to Current = b(_, Cost, NewPos)
. Where it backtracks to depends completely upon what other code you have in this clause (it's a bit hypothetically presented, so it could be anything).
Regarding is/2
is/2
is used to (a) evaluate a numeric expression as its second argument, and (b) unify the result of the expression evaluation with the first argument. Here are some examples, also showing the contrast with =/2
(unification):
| ?- X = A + B.
X = A+B
yes
Here, X
is unified with the term, A + B
. So X
is now instantiated with the term A+B
(which is the term, '+'(A, B)
)
| ?- A = 2, B = 3, X = A + B.
A = 2
B = 3
X = 2+3
yes
X
is unified with the term, A + B
. A
is unified with 2
(and so A
is instantiated with the value 2
), and B
is unified with 3
. So X
is unified with 2+3
(or `'+'(2,3)).
| ?- A = 2, B = 3, X is A + B.
A = 2
B = 3
X = 5
yes
The expression on the right hand side of is
(the second argument to is/2
) is evaluated yielding 5
. Then X
is instantiated to 5
.
| ?- A = 2, X is A + B.
uncaught exception: error(instantiation_error,(is)/2)
B
isn't instantiated, so the expression, A + B
cannot be evaluated, so is/2
fails due to an instantiation error.
| ?- A = 2, B = 3, Z = 5, Z is A + B.
A = 2
B = 3
Z = 5
yes
A
, B
, and Z
are all instantiated to numeric values, and Z is A + B
succeeds since A + B
evaluates to 5
, which is unifiable with Z
which also has the value 5
.
| ?- A = 2, B = 3, Z = 4, Z is A + B.
no
A
, B
, and Z
are all instantiated to numeric values, and Z is A + B
fails since A + B
evaluates to 5
, which is not unifiable with Z
which has the value 4
.
| ?- A = 2, B = 3, X = A + B, Z is X.
A = 2
B = 3
X = 2+3
Z = 5
yes
X
is unified with the term, A + B
, which is the term 2 + 3
since A
has been instantiated with 2
, and B
with 3
. Z
is unified with the evaluation of the expression X
(which is 2 + 3
) and so has the value 5
.