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

查看:16
本文介绍了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.

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

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

然后就可以查询是 _ 是 _ 吗?"并回答是"或未知".我不知道为什么如果谓词(我认为这就是所谓的火腿")不在数据库中,它为什么会出错,但如果另一部分不在数据库中就可以了.关于我做错了什么的任何想法?对不起,如果我第一次用序言做一些愚蠢的事情.如果这很重要,我正在使用 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天全站免登陆