我是Prolog的初学者,我正在处理一个看起来很愚蠢的问题,但我真的无法理解我做错了什么!好的,我有这个文件fruits.pl,里面有我这样的东西:
fruit(apple,small,sweet).
fruit(lemon,small,nosweet).
fruit(melon,big,sweet).
我已经(在该文件中创建了一个共存(X,Y)原子,检查两个水果是否可以放在盘子里。它工作正常!但现在我无法创建一个建议(X)将水果作为参数并返回可以放在同一个盘子中的水果列表。 问题是我试图做出类似的东西
suggest(X) :- findall(Y,fruit(Y,_,_), List), coexist(X,Y).
你怎么看?每当我尝试在swi prolog中运行它时,都会出现一个警告单例变量'当我按下
suggest(apple).
然后说错误.. 对不起我的英文:/
答案 0 :(得分:3)
Prolog中的谓词不会返回任何内容。您的目标是否满意,您可以将其解释为返回true
或false
。
您的谓词suggest(X)
应该包含另一个参数,该参数将绑定到与X
一起的水果列表。选项可以是:suggest(X, List)
,它描述了以下关系:List
表示与X
一起出现的所有成果。然后,你可以问:
?- suggest(apple, List).
List = [pear, cherry].
目标findall(Y, ... , ...)
在内部使用Y
变量,Y
在目标满足后仍未绑定。因此,您应该将coexist(X,Y)
移到findall/3
的第二个参数内,这是以所有可能的方式满足的目标。以下规则仅在X
实例化时才有效(<{1}})。
suggest(+X, -List)
您可以按照以下方式阅读:“suggest(X, List) :- findall(Y, (fruit(Y,_,_), coexist(X, Y)), List).
代表与List
共存的所有水果Y
。”
答案 1 :(得分:2)
当您尝试在Prolog中定义谓词时,首先假装您已经编写了该谓词,并从想象如何使用它开始。也就是说,您想要提出什么样的问题。
对我来说,好像coexist/2
已经描述了你想要的东西。顺便说一下,may_coexist/2
可能是一个更具描述性的名称。你为什么要把它放在一个单独的列表中?为什么要使用fruit/3
呢?但是为了这个问题,让我们假设这是有道理的。所以基本上你现在有一个关系fruit_compatible/2
:
fruit_compatible(F, G) :-
fruit(F, _, _),
may_coexist(F, G),
fruit(G, _, _). % maybe you want to add this?
现在,让我们假设您也想要这个列表。所以你会有一个关系fruit_suggestions/2
。怎么用?
?- fruit_suggestions(apple, L).
L = [cherry, pear].
或......应该是L = [pear, cherry]
吗?或两者兼而有之?
?- fruit_suggestions(lemon, L).
L = [orange].
所以每当我想要一个建议时,我都要想到一个水果。一直在想:应该是什么水果?幸运的是,在Prolog中有一种要求不高的方式:只需使用变量而不是水果!现在我们应该立刻得到所有建议!
?- fruit_suggestions(F, L).
F = apple, L = [cherry, pear] ;
F = lemon, L = [orange] ;
F = cromulon, L = [embiggy, mushfruit].
所以我们需要实现它,以便它会以这种方式运行。仅findall/3
并不能解决这个问题。手动实现它远非微不足道。但是setof/3
以完全相同的方式处理变量。许多微小的细节设计决策已经完成,就像列表将按升序排序一样。
fruit_suggestions(F, L) :-
setof(G, fruit_compatible(F, G), L).
编辑:由于下面的讨论,这里将是一个允许空列表的解决方案。请注意,这听起来微不足道,但事实并非如此。要查看此内容,请考虑以下问题:
?- fruit_suggestions(F, []).
这是什么意思? F
应该是什么?还有什么东西都没结果?在这种情况下,我们必须为所有生成解决方案。像F = badger ; F = 42 ; ...
一样。最有可能这没有多大意义。可能意图是那些与一切都不相容的水果。为此,我们需要添加一条新规则:
fruit_suggestions(F, []) :-
setof(t,X^Y^fruit(F,X,Y),_),
\+ fruit_compatible(F, _).
fruit_suggestions(F, L) :-
setof(G, fruit_compatible(F, G), L).