读取 prolog 中的输入并打印结果 [英] Read input in prolog and print result

查看:35
本文介绍了读取 prolog 中的输入并打印结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习 Prolog 的想法,这是我想要练习的内容:

I am learning Prolog ideas and here is what I want to practice:

我想写一个可以像这样工作的 Prolog 程序:

I want to write a Prolog program that can work like this:

?- input([apple,is,fruit]).
?- input([chicken,is,meat]).
?- input([Is,apple,meat]).
No, it is a fruit
?- input[(Is,chicken,meat])
Yes.

当我尝试实施这个程序时,我遇到了一些问题:

And when I was trying to implement this program, I got some problem:

(1) 我用这段代码试图读取输入并区分问题和断言,但失败了:

(1) I used this code trying to read the input and distinguish between questions and assertions, but it fails:

input([]).
input([X|R]) :- X is 'Is', write('test code read question'); write("test code read assertion").

(2) 我仍然对如何从输入消息中过滤有用信息感到困惑.例如,在 [Apple,is,fruit] 输入数组中,我只需要 applefruit.跳is字我们一般怎么做?

(2) I am still confused about How I can filter the useful information out from the input message. For example, in the [Apple,is,fruit]input array, all I need is apple and fruit. How do we normally do to jump the is word?

我不想给程序硬编码太多东西,更喜欢好的函数式编程风格来解决可以帮助我从中学习的问题.

I don't want to hardcode too many things to the program, and prefer a good functional programming style to solve the problem that can help me learn from it.

提前致谢.

推荐答案

仅仅因为我喜欢它们,我就倾向于使用定语从句语法 (DCG).然后你就可以很容易地做出语句并解析它们:

Just because I enjoy them, I'd be inclined towards a definite clause grammar (DCG). Then you can make statements and parse them fairly easily:

word(Word) --> [Word].
statement(Statement) --> 
    word(Thing), [is], word(Category), 
    { Statement =.. [Category, Thing] }.

这里使用 DCG 的技巧是您的语法正在转换为差异列表表示.括号内为普通Prolog代码;它周围的部分被解释为列表的文字部分或其他语法规则.所以 [Word] 匹配一个原子.我们实际上可以这样编写规则:

The trick going on here with DCGs is that your grammar is being transformed to a difference list representation. The part in brackets is normal Prolog code; the part around it is interpreted either as literal parts of the list or as other grammar rules. So [Word] is matching one atom. We could actually write the rule like this:

statement(Statement) -->
    [Thing, is, Category],
    { Statement =.. [Category, Thing] }.

它会产生相同的效果,而且可能更具可读性,但我喜欢迂腐.请特别注意 =.. 的使用,它将列表转换为事实,反之亦然(所以 [fruit, apple] 变成 fruit(apple)).

and it would have the same effect, and perhaps be more readable, but I like being pedantic. Note especially the use of =.., which converts lists into facts and vice versa (so [fruit, apple] becomes fruit(apple)).

使用 DCG 进行解析非常简单:使用 phrase/2:

Parsing with DCGs is quite easy: use phrase/2:

?- phrase(statement(X), [apple,is,fruit]).
X = fruit(apple).

然后你可以使用asserta将这些子句插入到动态存储中:

Then you can use asserta to insert these clauses into the dynamic store:

input(Text) :- 
    phrase(statement(Statement), Text),
    asserta(Statement).

例如:

?- input([apple,is,fruit]).
true.

?- fruit(X).
X = apple.

现在您可以编写另一个子句来解析查询:

Now you can write another clause for parsing queries:

query(Query) --> 
    ['Is'], word(Word), word(Category), 
    { Query =.. [Category, Word] }.

看起来非常相似!同样,如果您愿意,可以使用以下语法:

Looks very similar! And again, if you wanted, you could use this syntax:

query(Query) -->
    ['Is', Word, Category],
    { Query =.. [Category, Word] }.

现在您可能想编写一个子句,将两个语法规则组合成一个句子"规则:

Now you might want to write a clause to combine both grammar rules into one "sentence" rule:

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

试试看:

?- phrase(sentence(X), ['Is', apple, fruit]).
X = query(fruit(apple)).

?- phrase(sentence(X), [apple, 'is', fruit]).
X = statement(fruit(apple)) ;

您现在看到,我们不仅得到了解析的事实,而且还得到了一个包装器,它告诉我们它是语句还是查询.我们现在可以用这个代替语句和查询来解析,并像这样重写 input :

You see now we get not just the parsed fact, but also a wrapper that tells us whether it was a statement or a query. We can now parse with this instead of statement and query, and rewrite input like so:

input(Text) :-
    phrase(sentence(S), Text), perform(S).

我添加了一个辅助来处理工作:

I've added an auxiliary to handle the work:

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

当您添加更多语法抽象时,这将在以后方便:每个 perform 子句处理不同的句子"类型,因此您进行上面的解析并处理下面的工作.现在我们或多或少有了你想要的:

This will be convenient later as you add more grammatical abstractions: each perform clause handles a different "sentence" type, so you do your parsing above and handle the work below. And now we have, more or less, what you wanted:

?- input([apple,is,fruit]).
true ;
false.

?- input(['Is',apple,fruit]).
true.

?- input(['Is',banana,fruit]).
false.

您可以通过在您的 sentence 规则中引入删减并使用特殊输出处理真/假来改进事情,但我认为这是我想要进入的方向,特别是如果您愿意以便将来能够处理不同的语法.

You can improve things by introducing a cut in your sentence rule and handling true/false with special output, but I think this is the direction I'd want to go in, particularly if you want to be able to handle different syntax in the future.

这篇关于读取 prolog 中的输入并打印结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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