Prolog, error when querying a false statement

六月ゝ 毕业季﹏ 提交于 2019-12-02 20:26:36

问题


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.

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

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

回答1:


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).
⋮

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.

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.

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.

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. :)

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!

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.


来源:https://stackoverflow.com/questions/16173977/prolog-error-when-querying-a-false-statement

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!