captain
captain

Reputation: 1827

Get substring from a fact

So I've got facts that are written like this document(Title,Topic). I want to make a rule where with two arguments.The first one is Keys which is a list of keywords and the second one is the document. I want to get as a result the titles of the documents which cointain the keywords I've given. This is what I wrote till now:

isInDoc([],'no'). %Recursion stops here. Don't know what to put as 2nd argument
isInDoc([H|T],document(Title,_)) :-
    sub_string(case_insensitive,H,document(Title,_)),
    isInDoc(T,document(Title,_)).

What I've thought is that I read the head of the list of keywords and see if it is a substring of the title of the document. When I type document(Title,_) in SWI-Prolog I get the titles of the documents. I can't think of any other way to get access to the title of the document. If I do a question I get this error ERROR: table: sub_string/3: Type error:'text' expected, found document(_G6503,_G6504). Isn't document(Title,_) of type text?

Upvotes: 1

Views: 168

Answers (1)

CapelliC
CapelliC

Reputation: 60034

in SWI-Prolog, sub_string/5 has been introduced recently, but works only on strings. The correct predicate to use is sub_atom/5 (it is also ISO standard):

isInDoc(Tokens, document(Title, _)) :-
   member(Token, Tokens),
   sub_atom(Title, _,_,_, Token).

4 ?- document(T,_), isInDoc([and], document(T,_)).
T = 'Rules and Uncertainty' ;
false.

5 ?- document(T,_), isInDoc([and, certa], document(T,_)).
T = 'Rules and Uncertainty' ;
T = 'Rules and Uncertainty' ;
false.

I use member/2 to 'try' all tokens, instead of writing a recursive rule. Btw, since you expect that isInDoc/2 will fail when any of the tokens cannot be found, you can drop altogether the base case (but since you used no, that will never match document(_, _), the effect is the same).

edit Maybe the snippet can be made more useful separating the matching of atoms from the document:

isInDoc(Tokens, document(Title, _)) :- contains(Tokens, Title).

contains(Tokens, Atom) :-
   member(Token, Tokens),
   sub_atom(Atom, _,_,_, Token).

Upvotes: 3

Related Questions