Prolog,查询假语句时出错 [英] Prolog, error when querying a false statement

查看:34
本文介绍了Prolog,查询假语句时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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".

The assignment is to create rules from user input in the form " _ is a _." or " A _ is a _." This should respond with "ok".

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

And then be able to query "Is _ a _?" And respond with "yes" or "unknown". I have no idea why it's giving an error if the predicate(i think that's what it's called, "ham") is not in the database, but its fine with the other part not being in there. Any ideas as to what I'm doing wrong? And sorry if I'm doing something simply stupid, first time with prolog. I'm using SWI-Prolog V.6.2.6 if that matters. And how would I go about omitting the true or false return in the 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) ? 

推荐答案

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

First, what Prolog responds with is really an implementation detail. SWI responds "true," but some other implementations respond "ok." There's nothing to change about your code because of that, as long as you're getting affirmatives and negatives when you should.

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

Second, there is a difference between your dog and ham examples. Look at the database after your sample inputs have been processed:

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

dog(john).
⋮

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

Where's ham/1? Nowhere. When you asserta(dog(john)), Prolog becomes aware that dog/1 is a predicate, but that never happened with ham/1. So you have to decide if that query is well-formed, in which case you want to catch the exception or else pre-declare all your possible predicates with dynamic/1, or be happy that it isn't well-formed. Your use scenario will determine which is appropriate. For instance, you could just do this:

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

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

我怀疑您是否愿意为所有事情都这样做,因此您可能想查看 SWI-Prolog 的 捕获设施.有关如何处理它的示例,请参阅此答案底部的编辑.

I doubt you'll want to do that for everything, so you'll probably want to look at SWI-Prolog's catch facility. See the edit at the bottom of this answer for an example of how to handle it.

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

Also, I would probably rework the DCG a little bit to make it a little more general and simpler:

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 向下传播到您的其余代码中.

Also, there's no real need to make statement1. You can have a DCG rule with more than one body; even if you did need two bodies, you could have them both generate statement/1 structures to match in action/1; you certainly don't need to propagate statement1/1 down that far into the rest of your code.

最后一点,你不需要引用小写的原子.:)

Last remark, you don't need to quote lowercase atoms. :)

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

Overall I think you're doing a pretty good job here! This is hard stuff to learn, and the material online is pretty sparse. I hope you keep at it, you're probably starting to see the kinds of cool things you can do with Prolog and DCGs!

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

Edit: You can catch the error and handle it properly by replacing your last action/1 clause with this:

action(query(Q)) :- 
    catch((Q -> write(yes) ; write(unknown)), 
          error(existence_error(procedure, _), _), 
          write(unknown)), 
    nl.

这篇关于Prolog,查询假语句时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆