Reputation: 13915
Cannot increment variable N
by 1 using is/2
predicate. N
is always 0 in the repeat loop. Why? How to increment it?
:- dynamic audible/1, flashes/1,tuned/1.
audible(false).
flashes(false).
tuned(false).
turn :-
N is 0 ,
repeat ,
(
incr(N,N1) ,
N1 =:= 5000 ,
audible(true) ,
flashes(true) -> retractall(tuned) ,
retractall(flashes) ,
retractall(audible) ,
assert( tuned(true) ) ,
assert( flashes(true) ) ,
assert( audible(true) )
) .
incr(X,X1) :- X1 is X+1 .
Upvotes: 0
Views: 1528
Reputation: 74277
I haven't a clue what you're trying to accomplish here, but it would appear that you're trying to write procedural prolog code.
It doesn't work.
Prolog variables are write-once: having been unified with an object they cease to be variable. They become that object, until that unification is undone via backtracking.
You need to learn to think recursively and to use recursion loops to do what you want.
Your turn/0 predicate
turn :-
N is 0 ,
repeat ,
(
incr(N,N1) ,
N1 =:= 5000 ,
audible(true) ,
flashes(true) -> retractall(tuned) ,
retractall(flashes) ,
retractall(audible) ,
assert( tuned(true) ) ,
assert( flashes(true) ) ,
assert( audible(true) )
) .
does the following. It:
At this point, you're back to where you started, with N bound to 0.
Wash, rinse, repeat.
Upvotes: 1
Reputation: 22803
Because N is 0
. Variables in Prolog are not assignables. Here's what happens if you trace your loop:
?- trace, turn.
Call: (7) turn ?
Call: (8) _G492 is 0 ?
Exit: (8) 0 is 0 ?
Call: (8) repeat ?
Exit: (8) repeat ?
Call: (8) incr(0, _G493) ?
Call: (9) _G495 is 0+1 ?
Exit: (9) 1 is 0+1 ?
Exit: (8) incr(0, 1) ?
Call: (8) 1=:=5000 ?
Fail: (8) 1=:=5000 ?
Redo: (8) repeat ?
Exit: (8) repeat ?
Call: (8) incr(0, _G493) ?
Call: (9) _G495 is 0+1 ?
Exit: (9) 1 is 0+1 ?
Exit: (8) incr(0, 1) ?
Call: (8) 1=:=5000 ?
Fail: (8) 1=:=5000 ?
Redo: (8) repeat ?
Exit: (8) repeat ?
Call: (8) incr(0, _G493) ?
Call: (9) _G495 is 0+1 ?
Exit: (9) 1 is 0+1 ?
Exit: (8) incr(0, 1) ?
Call: (8) 1=:=5000 ?
Fail: (8) 1=:=5000 ?
Redo: (8) repeat ?
See what's happening there? You're repeatedly asking if 1 is 5000, which fails, and then you try again. But the value of N and N1 will never change within the body of a predicate. Prolog does not have block-scoped variables like you're accustomed to. You need to make the body of the loop into a separate predicate and use recursion to accomplish what you're trying to do. It's going to look something like this:
turn :- loop(0).
loop(5000) :-
audible(true), ...
loop(N) :-
incr(N, N1),
loop(N1).
By the way, there's already a predicate succ/2
that does what you're trying to do with incr/2
.
Upvotes: 3