1
votes

let say i have the following facts :

book(65).
own(named('Peter'), 65).

now got the query as a list of clauses :

 [what(A), own(named('Peter'), A)] 

or

 [who(X), book(A), own(X, A)] .

how do I make a rule that accept this list and return the result. Keep in mind that the question could be Why,When,Who...

I went the usual way :

query_lst([]).
%% query_lst([what(Q)|T], Q) :- query_lst(T). 
query_lst([H|T]) :- write('?- '),writeln(H), 
    call(H), query_lst(T).

but this does not allow binding of Q in wh(Q) to the answer which could be in any of the facts that are called by call()


Additional complication I did not forsee is that the query :

(what(A), own(named('Peter'), A).

would fail, because there is no what(X), fact in the DB. I have to just bind somehow the variable A /that is in what()/ to query_lst(Goals,A) and of course remove what(X) from the list /which i can do with select/3 /

any idea how to bind list-Wh-var to query_lst result ?


my current solution (assumes Q is first element):

 query_lst([G|Gs],Res) :- G =.. [Q,Res], member(Q,[what,why,who,when]), lst2conj(Gs,Conj), call(Conj).
2

2 Answers

1
votes

Simply convert the list of goals into a conjunction and call it:

list_to_conjunction([], true).
list_to_conjunction([Goal| Goals], Conjunction) :-
    list_to_conjunction(Goals, Goal, Conjunction).

list_to_conjunction([], Conjunction, Conjunction).
list_to_conjunction([Next| Goals], Goal, (Goal,Conjunction)) :-
    list_to_conjunction(Goals, Next, Conjunction).

Then:

query_list(Goals) :-
    list_to_conjunction(Goals, Conjunction),
    call(Conjunction).
1
votes

You got an answer, but it was an answer to your question, not to what you really wanted. Also, you edited your question after you accepted that answer, which isn't very helpful. Typically it's better to open a new question when you have... a new question.

Here is an answer to what you seem to want, which is not exactly what you asked. You have lists of the form [WhPart | Rest] where the WhPart is a wh-word with a variable, and the Rest is a list of goals. You want to execute these goals and get the variable in the wh-term bound.

The good news is that, since the variable in the wh-word also occurs in the goals, it will be bound if you execute them. No extra work is needed. Executing the goals is enough. If the wh-part is really at the start of the list, you can do the whole thing like this:

query([_WhPart | Body]) :-
    call_body(Body).

call_body([]).
call_body([Goal | Goals]) :-
    call(Goal),
    call_body(Goals).

For example:

?- query([who(X), book(A), own(X, A)]).
X = named('Peter'),
A = 65.

?- query([what(A), own(named('Peter'), A)]).
A = 65.

As you can see, there is no need to convert the query to a conjunctive goal: Executing the queries in sequence is exactly the same as executing their conjunction.

Also, it doesn't actually matter which wh-word is used; the only thing that really matters is the variable contained within the term. For this reason the above version does no checking at all, and the _WhPart could be anything. If you want to check that it is a valid term, you can do the following:

query([WhPart | Body]) :-
    wh(WhPart),
    call_body(Body).

wh(who(_X)).
wh(what(_X)).
wh(when(_X)).

This buys you some "type checking":

?- query([foo(A), own(named('Peter'), A)]).
false.

But not a lot, since you don't know if the wh-word actually fits what is being asked:

?- query([when(A), own(named('Peter'), A)]).
A = 65.