在prolog中读取输入并打印结果

在prolog中读取输入并打印结果,prolog,dcg,Prolog,Dcg,我正在学习Prolog理念,以下是我想练习的内容: 我想写一个Prolog程序,可以这样工作: ?- input([apple,is,fruit]). ?- input([chicken,is,meat]). ?- input([Is,apple,meat]). No, it is a fruit ?- input[(Is,chicken,meat]) Yes. statement(Statement) --> [Thing, is, Category], { State

我正在学习Prolog理念,以下是我想练习的内容:

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

?- input([apple,is,fruit]).
?- input([chicken,is,meat]).
?- input([Is,apple,meat]).
No, it is a fruit
?- input[(Is,chicken,meat])
Yes.
statement(Statement) -->
    [Thing, is, Category],
    { Statement =.. [Category, Thing] }.
当我试图实施这个计划时,我遇到了一些问题:

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

input([]).
input([X|R]) :- X is 'Is', write('test code read question'); write("test code read assertion").
(2) 我仍然对如何从输入消息中过滤出有用的信息感到困惑。例如,在
[Apple,is,fruit]
输入数组中,我只需要
Apple
fruit
。我们通常如何跳转
is
单词

我不想把太多的东西硬编码到程序中,我更喜欢用一种好的函数式编程风格来解决这个问题,这样可以帮助我从中学习


提前谢谢。

您没有使用Prolog语法。您描述的内容可以通过这种方式实现(未经测试的代码):


注意以大写字母开头的符号:这些是变量,而不是原子。

您没有使用Prolog语法。您描述的内容可以通过这种方式实现(未经测试的代码):


注意以大写字母开头的符号:这些是变量,而不是原子。

仅仅因为我喜欢它们,我倾向于使用定冠词语法(DCG)。然后,您可以制作语句并相当轻松地解析它们:

word(Word) --> [Word].
statement(Statement) --> 
    word(Thing), [is], word(Category), 
    { Statement =.. [Category, Thing] }.
这里使用DCGs的诀窍是将语法转换为差异列表表示。括号中的部分为普通Prolog代码;它周围的部分被解释为列表的文字部分或其他语法规则。所以[Word]匹配一个原子。我们实际上可以这样写规则:

?- input([apple,is,fruit]).
?- input([chicken,is,meat]).
?- input([Is,apple,meat]).
No, it is a fruit
?- input[(Is,chicken,meat])
Yes.
statement(Statement) -->
    [Thing, is, Category],
    { Statement =.. [Category, Thing] }.
它也会有同样的效果,也许更具可读性,但我喜欢迂腐。请特别注意,
=…
,它将列表转换为事实,反之亦然(因此
[水果,苹果]
变成
水果(苹果)

使用DCGs进行解析非常简单:使用
短语/2

?- phrase(statement(X), [apple,is,fruit]).
X = fruit(apple).
然后可以使用
asserta
将以下子句插入动态存储:

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

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

?- fruit(X).
X = apple.
现在,您可以编写另一个子句来解析查询:

query(Query) --> 
    ['Is'], word(Word), word(Category), 
    { Query =.. [Category, Word] }.
看起来很像!同样,如果需要,可以使用以下语法:

query(Query) -->
    ['Is', Word, Category],
    { Query =.. [Category, Word] }.
现在,您可能需要编写一个子句,将两个语法规则合并为一个“句子”规则:

试一试:

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

?- phrase(sentence(X), [apple, 'is', fruit]).
X = statement(fruit(apple)) ;
你看,现在我们得到的不仅仅是解析的事实,还有一个包装器,告诉我们它是一个语句还是一个查询。现在,我们可以用它而不是语句和查询进行解析,并重写
input
,如下所示:

input(Text) :-
    phrase(sentence(S), Text), perform(S).
我添加了一个辅助工具来处理这项工作:

perform(statement(S)) :- asserta(S).
perform(query(Q))     :- Q.
这在以后添加更多语法抽象时会很方便:每个
perform
子句处理不同的“句子”类型,因此您可以执行上面的解析并处理下面的工作。现在我们或多或少有了你想要的:

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

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

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

你可以通过在你的
句子
规则中引入一个切入点,并用特殊的输出处理真/假,来改进事情,但我认为这是我想要走的方向,特别是如果你想在将来能够处理不同的语法。

仅仅因为我喜欢它们,我倾向于使用确定子句语法(DCG)。然后,您可以制作语句并相当轻松地解析它们:

word(Word) --> [Word].
statement(Statement) --> 
    word(Thing), [is], word(Category), 
    { Statement =.. [Category, Thing] }.
这里使用DCGs的诀窍是将语法转换为差异列表表示。括号中的部分为普通Prolog代码;它周围的部分被解释为列表的文字部分或其他语法规则。所以[Word]匹配一个原子。我们实际上可以这样写规则:

?- input([apple,is,fruit]).
?- input([chicken,is,meat]).
?- input([Is,apple,meat]).
No, it is a fruit
?- input[(Is,chicken,meat])
Yes.
statement(Statement) -->
    [Thing, is, Category],
    { Statement =.. [Category, Thing] }.
它也会有同样的效果,也许更具可读性,但我喜欢迂腐。请特别注意,
=…
,它将列表转换为事实,反之亦然(因此
[水果,苹果]
变成
水果(苹果)

使用DCGs进行解析非常简单:使用
短语/2

?- phrase(statement(X), [apple,is,fruit]).
X = fruit(apple).
然后可以使用
asserta
将以下子句插入动态存储:

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

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

?- fruit(X).
X = apple.
现在,您可以编写另一个子句来解析查询:

query(Query) --> 
    ['Is'], word(Word), word(Category), 
    { Query =.. [Category, Word] }.
看起来很像!同样,如果需要,可以使用以下语法:

query(Query) -->
    ['Is', Word, Category],
    { Query =.. [Category, Word] }.
现在,您可能需要编写一个子句,将两个语法规则合并为一个“句子”规则:

试一试:

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

?- phrase(sentence(X), [apple, 'is', fruit]).
X = statement(fruit(apple)) ;
你看,现在我们得到的不仅仅是解析的事实,还有一个包装器,告诉我们它是一个语句还是一个查询。现在,我们可以用它而不是语句和查询进行解析,并重写
input
,如下所示:

input(Text) :-
    phrase(sentence(S), Text), perform(S).
我添加了一个辅助工具来处理这项工作:

perform(statement(S)) :- asserta(S).
perform(query(Q))     :- Q.
这在以后添加更多语法抽象时会很方便:每个
perform
子句处理不同的“句子”类型,因此您可以执行上面的解析并处理下面的工作。现在我们或多或少有了你想要的:

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

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

?- input(['Is',banana,fruit]).
false.
你可以通过在你的
句子
规则中引入一个切入点,并用特殊的输出处理真/假,来改善情况,但我认为这是我想朝的方向,特别是如果你希望将来能够处理不同的语法