문제

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 variable Acc is uninstantiated (has no value) so your Acc1 is Acc + 1 fails since there's nothing to add to 1 (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.

score(Tags, Count, Document) :-
    score(Tags, 0, Count, Document).      % Start accumulator at zero

% No more tags, so the current accumulator is what our resulting count is
%   and we don't care what the document argument is at this point
score([], A, A, _).

score([Tag|Tags], Acc, Count, document(Title,_)) :-
    sub_string(case_insensitive, Tag, Title),     % Check for Tag in Title
    Acc1 is Acc + 1,                              % Increment acc if found
    score(Tags, Acc1, Count, document(Title,_)).  % Score remaining tags

But there's one more problem: if sub_string/3 ever fails (a single Tag isn't found) then score/4 will fail completely. So there needs to be a continued recursion if Tag isn't found but without incrementing the accumulator. The easiest way to do this is using a Prolog if-then-else construct in the recursive score/4 predicate:

score([Tag|Tags], Acc, Count, document(Title,_)) :-
    (   sub_string(case_insensitive, Tag, Title)  % Check for Tag in Title
    ->  Acc1 is Acc + 1                           % Increment acc if found
    ;   Acc1 = Acc                                % Otherwise, no increment
    ),
    score(Tags, Acc1, Count, document(Title,_)).  % Score remaining tags

Using the above, your query, ?- document(T, _), score([rule], Acc, document(T,_)). should work. Since there's only one tag, the result will either be Acc = 0 or Acc = 1.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top