将子句列表转换为查询?
Converting list of clauses to a query?
假设我有以下事实:
book(65).
own(named('Peter'), 65).
现在将查询作为子句列表获取:
[what(A), own(named('Peter'), A)]
或
[who(X), book(A), own(X, A)] .
如何制定接受此列表和 return 结果的规则。请记住,问题可能是为什么、何时、谁...
我走的是平常的路:
query_lst([]).
%% query_lst([what(Q)|T], Q) :- query_lst(T).
query_lst([H|T]) :- write('?- '),writeln(H),
call(H), query_lst(T).
但这不允许将 wh(Q) 中的 Q 绑定到答案,而答案可能存在于 call()
调用的任何事实中
我没有预见到的其他并发症是查询:
(what(A), own(named('Peter'), A).
会失败,因为数据库中没有 what(X) 事实。
我必须以某种方式将 what()/ 中的变量 A / 绑定到 query_lst(Goals,A) 并且当然从列表中删除 what(X) /我可以用 select/3 /
知道如何将 list-Wh-var 绑定到 query_lst 结果吗?
我当前的解决方案(假设 Q 是第一个元素):
query_lst([G|Gs],Res) :- G =.. [Q,Res], member(Q,[what,why,who,when]), lst2conj(Gs,Conj), call(Conj).
只需将目标列表转换为连词并调用它:
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).
然后:
query_list(Goals) :-
list_to_conjunction(Goals, Conjunction),
call(Conjunction).
您得到了答案,但这是对您问题的回答,而不是您真正想要的。此外,您在接受该答案后编辑了您的问题,这不是很有帮助。通常,当您有...一个新问题时,最好打开一个新问题。
这里是你似乎想要的的答案,这与你问的不完全一样。您有 [WhPart | Rest]
形式的列表,其中 WhPart
是带有变量的 wh-word,而 Rest
是目标列表。您想执行这些目标并获得 wh-term 范围内的变量。
好消息是,由于wh-word中的变量也出现在目标中,如果你执行它们,它就会被绑定。不需要额外的工作。执行目标就足够了。如果 wh-part 真的在列表的开头,你可以这样做:
query([_WhPart | Body]) :-
call_body(Body).
call_body([]).
call_body([Goal | Goals]) :-
call(Goal),
call_body(Goals).
例如:
?- query([who(X), book(A), own(X, A)]).
X = named('Peter'),
A = 65.
?- query([what(A), own(named('Peter'), A)]).
A = 65.
如您所见,无需将查询转换为联合目标:按顺序执行查询与执行它们的联合完全相同。
此外,使用哪个 wh-word 实际上并不重要;唯一真正重要的是术语中包含的变量。由于这个原因,上面的版本根本没有检查, _WhPart
可以是任何东西。如果要检查它是否是有效术语,可以执行以下操作:
query([WhPart | Body]) :-
wh(WhPart),
call_body(Body).
wh(who(_X)).
wh(what(_X)).
wh(when(_X)).
这会给你带来一些“类型检查”:
?- query([foo(A), own(named('Peter'), A)]).
false.
但不是很多,因为您不知道 wh-word 是否真的符合所问的内容:
?- query([when(A), own(named('Peter'), A)]).
A = 65.
假设我有以下事实:
book(65).
own(named('Peter'), 65).
现在将查询作为子句列表获取:
[what(A), own(named('Peter'), A)]
或
[who(X), book(A), own(X, A)] .
如何制定接受此列表和 return 结果的规则。请记住,问题可能是为什么、何时、谁...
我走的是平常的路:
query_lst([]).
%% query_lst([what(Q)|T], Q) :- query_lst(T).
query_lst([H|T]) :- write('?- '),writeln(H),
call(H), query_lst(T).
但这不允许将 wh(Q) 中的 Q 绑定到答案,而答案可能存在于 call()
调用的任何事实中我没有预见到的其他并发症是查询:
(what(A), own(named('Peter'), A).
会失败,因为数据库中没有 what(X) 事实。 我必须以某种方式将 what()/ 中的变量 A / 绑定到 query_lst(Goals,A) 并且当然从列表中删除 what(X) /我可以用 select/3 /
知道如何将 list-Wh-var 绑定到 query_lst 结果吗?
我当前的解决方案(假设 Q 是第一个元素):
query_lst([G|Gs],Res) :- G =.. [Q,Res], member(Q,[what,why,who,when]), lst2conj(Gs,Conj), call(Conj).
只需将目标列表转换为连词并调用它:
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).
然后:
query_list(Goals) :-
list_to_conjunction(Goals, Conjunction),
call(Conjunction).
您得到了答案,但这是对您问题的回答,而不是您真正想要的。此外,您在接受该答案后编辑了您的问题,这不是很有帮助。通常,当您有...一个新问题时,最好打开一个新问题。
这里是你似乎想要的的答案,这与你问的不完全一样。您有 [WhPart | Rest]
形式的列表,其中 WhPart
是带有变量的 wh-word,而 Rest
是目标列表。您想执行这些目标并获得 wh-term 范围内的变量。
好消息是,由于wh-word中的变量也出现在目标中,如果你执行它们,它就会被绑定。不需要额外的工作。执行目标就足够了。如果 wh-part 真的在列表的开头,你可以这样做:
query([_WhPart | Body]) :-
call_body(Body).
call_body([]).
call_body([Goal | Goals]) :-
call(Goal),
call_body(Goals).
例如:
?- query([who(X), book(A), own(X, A)]).
X = named('Peter'),
A = 65.
?- query([what(A), own(named('Peter'), A)]).
A = 65.
如您所见,无需将查询转换为联合目标:按顺序执行查询与执行它们的联合完全相同。
此外,使用哪个 wh-word 实际上并不重要;唯一真正重要的是术语中包含的变量。由于这个原因,上面的版本根本没有检查, _WhPart
可以是任何东西。如果要检查它是否是有效术语,可以执行以下操作:
query([WhPart | Body]) :-
wh(WhPart),
call_body(Body).
wh(who(_X)).
wh(what(_X)).
wh(when(_X)).
这会给你带来一些“类型检查”:
?- query([foo(A), own(named('Peter'), A)]).
false.
但不是很多,因为您不知道 wh-word 是否真的符合所问的内容:
?- query([when(A), own(named('Peter'), A)]).
A = 65.