0
input :-
read_line_to_codes(user_input, Input),
string_to_atom(Input,Atoms),
atomic_list_concat(Alist, ' ', Atoms),
phrase(sentence(S), Alist),
action(S).


statement(Rule) --> [Noun, 'is', 'a', Object], { Rule =.. [Object, Noun]}.
statement1(Rule) --> ['A', Noun, 'is', 'a', Object], { Rule =.. [Object, Noun]}.
query(Fact) --> ['Is', Noun, 'a', Object], { Fact =.. [Object, Noun]}.

sentence(statement(S)) --> statement(S).
sentence(statement1(S))--> statement1(S).
sentence(query(Q)) --> query(Q).


action(statement(S)) :- asserta(S) -> write(ok).
action(statement1(S)) :- asserta(S) -> write(ok).
action(query(Q)) :-( Q -> write(yes); write(unknown)), nl.

任务是根据用户输入以“_ 是 _”的形式创建规则。或“一个_是一个_。” 这应该以“ok”响应。

然后能够查询“Is _ a _?” 并回答“是”或“未知”。我不知道为什么如果谓词(我认为这就是所谓的“火腿”)不在数据库中,它为什么会出错,但如果另一部分不在数据库中就可以了。关于我做错了什么的任何想法?对不起,如果我第一次用序言做一些愚蠢的事情。如果这很重要,我正在使用 SWI-Prolog V.6.2.6。我将如何在输出中省略 true 或 false 回报

   11 ?- input.
   |: john is a dog
   ok
   true .

   12 ?- input.
   |: Is john a dog
   yes
   true.


   13 ?- input.
   |: Is abraham a dog
   unknown
   false.

   14 ?- input.
   |: Is john a ham
   ERROR: action/1: Undefined procedure: ham/1
   Exception: (8) ham(john) ? 
4

1 回答 1

0

首先,Prolog 响应的实际上是一个实现细节。SWI 响应“true”,但其他一些实现响应“ok”。因此,只要您在应该得到肯定和否定时,您的代码就没有什么可以改变的。

其次,您的狗和火腿示例之间存在差异。处理完样本输入后查看数据库:

?- listing.
⋮ 
:- dynamic dog/1.

dog(john).
⋮

在哪里ham/1?无处。当你 时asserta(dog(john)),Prolog 会意识到 thatdog/1是一个谓词,但这从未发生在ham/1. 因此,您必须确定该查询是否格式正确,在这种情况下您要捕获异常,或者使用 预先声明所有可能的谓词dynamic/1,或者对它的格式不正确感到高兴。您的使用场景将确定哪个是合适的。例如,您可以这样做:

?- [user].
|: :- dynamic ham/1.
|: % user://2 compiled 0.00 sec, 1 clauses
true.

?- input.
|: Is john a ham
false.

我怀疑你会想要对所有事情都这样做,所以你可能想看看 SWI-Prolog 的catch facility。有关如何处理它的示例,请参阅此答案底部的编辑。

此外,我可能会稍微修改 DCG 以使其更通用和更简单:

article --> [a].
article --> [the].
article --> [].

noun(Noun) --> article, [Noun].

statement(Rule) --> noun(Noun), [is], noun(Object), { Rule =.. [Object, Noun] }.
query(Fact) --> ['Is'], noun(Noun), noun(Object), { Fact =.. [Object, Noun]}.

sentence(statement(S)) --> statement(S).
sentence(query(Q)) --> query(Q).

action(statement(S)) :- asserta(S).
action(query(Q)) :- Q.

此外,没有真正需要制作statement1. 您可以拥有一个包含多个实体的 DCG 规则;即使您确实需要两个主体,也可以让它们都生成statement/1匹配的结构action/1;您当然不需要将statement1/1那么远的内容传播到其余代码中。

最后一句话,你不需要引用小写的原子。:)

总的来说,我认为你在这里做得很好!这东西很难学,网上的资料也很少。我希望你坚持下去,你可能已经开始看到你可以用 Prolog 和 DCG 做的很酷的事情了!

编辑:您可以通过将最后一个action/1子句替换为以下内容来捕获错误并正确处理它:

action(query(Q)) :- 
    catch((Q -> write(yes) ; write(unknown)), 
          error(existence_error(procedure, _), _), 
          write(unknown)), 
    nl.
于 2013-04-23T16:48:06.293 回答