So I want to give a list of keywords and, whenever a word is encountered in a string, I will increment my counter. So I've been playing around for a while but I can't make it work. This is what I've done. Whenever I run a question I get this type of error: ERROR: score/3: Arguments are not sufficiently instantiated
.
score([],0,document(Title,_)).
score([H|T],Acc,document(Title,_)):-
sub_string(case_insensitive,H,Title),
Acc1 is Acc + 1,
score(T,Acc1,document(Title,_)).
My queries are written like this: ?- document(T,_),score([rule],Acc,document(T,_)).
When you query
score([rule],Acc,document(T,_))
, the variableAcc
is uninstantiated (has no value) so yourAcc1 is Acc + 1
fails since there's nothing to add to1
(arguments are not sufficiently instantiated). Also, your accumulator keeps increasing in recursion, but your base case triggers when the accumulator goes to zero (i.e., your recursive base case assumes that the accumulator is decreasing to zero).It looks like you've seen use of accumulators before, but you're mixing two different methods for how they're used (counting up or counting down), and you don't have an initial predicate which starts the accumulator, so you're attempting to do this from the initial query.
Here's an annotated working version. You need to start by having an initial accumulator of zero, which will then count up.
But there's one more problem: if
sub_string/3
ever fails (a singleTag
isn't found) thenscore/4
will fail completely. So there needs to be a continued recursion ifTag
isn't found but without incrementing the accumulator. The easiest way to do this is using a Prolog if-then-else construct in the recursivescore/4
predicate:Using the above, your query,
?- document(T, _), score([rule], Acc, document(T,_)).
should work. Since there's only one tag, the result will either beAcc = 0
orAcc = 1
.