我正在写一个小Prolog程序,预计会做以下事情:
?-input([allan,is,a,name]).
true.
?-input([Is,allan,a,name]).
true.
这是我的代码:
% Simple answering agent
input(Text) :-
phrase(sentence(S), Text),
perform(S).
sentence(statement(S)) --> statement(S).
sentence(query(Q)) --> query(Q).
statement(Statement) -->
[Thing, 'is', 'a', Category],
{ Statement =.. [Category, Thing]}.
query(Query) -->
['Is', Thing, 'a', Category],
{ Query =.. [Category, Thing]}.
perform(statement(S)) :- asserta(S).
perform(query(Q)) :- Q.
input([allan,is,a,name]).
部分似乎工作正常,但查询部分出现问题,如果我输入input([Is,allan,a,name]).
,则打印
Is = 'Is'
有人可以帮我看一下这个问题,谢谢。
答案 0 :(得分:2)
嗯,问题是Is
是一个变量,因此prolog实例化它(使用'Is'
)。最好确保列表中的所有成员都是原子,但为了快速修复,您可以这样做:
query(Query) -->
[_, Thing, 'a', Category],
{ Query =.. [Category, Thing]}.
这样,Is
将不会被实例化,而prolog只会说真的。唯一的问题是语句可以被解释为查询:
9 ?- input([allan, is, a, name]).
true ;
false.
10 ?- input([is, is, a, name]).
true .
11 ?- input([allan, is, a, name]).
true ;
true.
可以通过一些削减修复(或者说Thing
应该与'is'
不同 - 如果可以接受的话)
编辑:对于更通用的解决方案:它实际上取决于您要解析的句子类型以及用户可以做出的妥协。例如,有可能让他给你一些prolog原子的话;如果请求以大写字母开头的单词,则必须使用''
。否则,最好只用字符串/原子('Is allan a name'
或"Is allan a name"
)给出它们。将它与单个原子分开很容易:use atomic_list_concat/3。对于what is allan
,你仍然不需要做一些特殊的事情;这是一个3个字的句子,其余的是4个,所以你可以立即分开。