Reputation: 1373
I got this code that has to run a database as long as N > Order. My code only runs once :/ ?
display(N) :-
w(Order,_,Word,Class),
N > Order -> (write(Word), write(' '), write(Class)),
nl, fail .
Thanks in advance!
Upvotes: 2
Views: 129
Reputation: 5858
your problem is the way you use ->
First of all, the code is interpreted as:
display(N) :-
( w(Order,_,Word,Class),
N > Order )
) ->
( write(Word),
write(' '),
write(Class)
),
nl, fail .
->
destroys choice points meaning that it will not try to call w/3
again.
You could (probably) make it work like this:
display(N) :-
(w(Order,_,Word,Class),
N > Order )-> (write(Word), write(' '), write(Class)),
nl, fail .
but in the end it's really ugly code and, as you have seen, prone to bugs. A better way is to use forall/2
:
display2(N) :-
forall(w(Order, _, Word, Class),
(N > Order ->
writef("%t %t \n", [Word,Class]); true)).
still, this will examine the whole database and print if N>Order
. It is a bit unclear from your description if this is the desired behaviour but if you want to stop at the first element that is larger you could do something like:
display2(N) :-
catch((forall(w(Order, _, Word, Class),
(N > Order ->
writef("%t %t \n", [Word,Class]); throw(end))), end, true)).
not the most declarative way to do it but I'm not sure what's the best way to model it without knowing what w/4
is (I assumed that it is some prolog clauses but it could be a predicate accessing a DB though the ODBC layer)
Upvotes: 4
Reputation: 60034
I think you forgot the 'else' branch, and the precedence of (->)/2, that's higher that (,)/2, inhibits the intended order. Try
display(N) :-
w(Order,_,Word,Class),
( N > Order -> write(Word), write(' '), write(Class), nl ; true ),
fail .
Upvotes: 3