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

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

问题描述

我正在学习 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)) ;

您现在看到,我们不仅得到了解析的事实,而且还得到了一个包装器,它告诉我们它是一个语句还是一个查询.我们现在可以用 this 而不是语句和查询来解析,并像这样重写 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.

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

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