Prolog,查询错误陈述时出错

时间:2013-04-23 15:56:42

标签: prolog dcg

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.

分配是以“_ is a _”形式从用户输入创建规则。或“A _是_。”这应该回答“ok”。

然后能够查询“Is _ a _?”并回答“是”或“未知”。 我不知道为什么它会给出一个错误,如果谓词(我认为这就是它所谓的“火腿”)不在数据库中,但它很好,其他部分不在那里。关于我做错了什么的任何想法?对不起,如果我做一些简单的愚蠢,第一次与prolog。如果重要的话,我正在使用SWI-Prolog V.6.2.6。我将如何省略ouput中的真或假回报

   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) ? 

1 个答案:

答案 0 :(得分:0)

首先,Prolog回应的内容实际上是一个实现细节。 SWI响应“true”,但其他一些实现响应“ok”。由于这一点,你的代码没有什么可以改变的,只要你应该得到肯定和否定。

其次,你的狗和火腿的例子有所不同。处理完样本输入后查看数据库:

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

dog(john).
⋮

ham/1的位置?无处。当您asserta(dog(john))时,Prolog会发现dog/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.