简体   繁体   English

正确使用findall / 3,尤其是最后一个结果参数

[英]Correct use of findall/3, especially the last result argument

I'm a beginner in Prolog and I am dealing with a problem that might seem stupid to you, but I really can't understand what I'm doing wrong! 我是Prolog的初学者,我正在处理一个可能对您来说很愚蠢的问题,但是我真的不明白我在做什么错! Ok, I have this file fruits.pl and inside that I have something like this: 好的,我有这个文件fruits.pl,里面有这样的东西:

fruit(apple,small,sweet).
fruit(lemon,small,nosweet).
fruit(melon,big,sweet).

I have already (inside that file made a coexist(X,Y) atom that checks if two fruits can be put together in a plate. It works fine! But now I can't create a suggest(X) that takes as a parameter a fruit and returns a list of fruits that can be put together in the same plate. The thing is I was trying to make something like that 我已经(在该文件中创建了一个coexist(X,Y)原子,该原子检查是否可以将两个水果放到盘子中。它正常工作!但是现在我无法创建以参数为参数的suggest(X)水果,并返回可以放在同一盘子中的水果清单。问题是我正在尝试制作类似的东西

suggest(X) :- findall(Y,fruit(Y,_,_), List), coexist(X,Y).

What do you think? 你怎么看? Every time I try to run this in swi prolog there is a warning 'singleton variable' and when I press 每次我尝试在swi序言中运行此命令时,都会出现一个警告“单变量”,当我按

suggest(apple).

then it says false.. sorry for my english :/ 然后它说假..对不起我的英语:/

Predicates in Prolog do not return anything. Prolog中的谓词不返回任何内容。 You have goals that are satisfied or not and you can interpret that as returning true or false . 您的目标是否得到满足,您可以将其解释为返回truefalse

Your predicate suggest(X) should contain another parameter that will be bound to the list of fruits that go together with X . 您的谓词suggest(X)应该包含另一个参数,该参数将绑定到与X一起使用的水果列表中。 An option would be: suggest(X, List) which describes the following relation: List represents all the fruits that go together with X . 一个选项是: suggest(X, List) ,它描述以下关系: List表示与X在一起的所有水果。 Then, you could ask: 然后,您可以问:

?- suggest(apple, List).
List = [pear, cherry].

The goal findall(Y, ... , ...) uses the Y variable internally and Y is still unbound after the goal is satisfied. 目标findall(Y, ... , ...)在内部使用Y变量,并且在满足目标后, Y仍未绑定。 So, you should move coexist(X,Y) inside the second argument of findall/3 which is the goal that is satisfied in all possible ways. 因此,您应该在findall/3的第二个参数内移动coexist(X,Y) ,这是所有可能满足的目标。 Th rule below works only if X is instantiated ( suggest(+X, -List) ). 下面钍规则,如果只能X被实例化( suggest(+X, -List) )。

suggest(X, List) :- findall(Y, (fruit(Y,_,_), coexist(X, Y)), List).

You can read this as follows: " List represents all fruits Y that coexist with X ". 您可以阅读以下内容:“ List代表与X共存的所有水果Y ”。

When you try to define a predicate in Prolog, first of all pretend that you have written that predicate already and start with imagining how you would use it. 当您尝试在Prolog中定义谓词时,首先假设您已经编写了该谓词,然后开始想象如何使用它。 That is, what queries you would like to pose. 也就是说,您要提出什么查询。

To me, it looks as if coexist/2 already describes what you want. 在我看来, coexist/2已经描述了您想要的内容。 BTW, may_coexist/2 might be a more descriptive name. 顺便说一句, may_coexist/2可能是一个更具描述性的名称。 Why do you want this in a separate list? 为什么要在单独的列表中? And why using fruit/3 at all? 为什么要使用fruit/3 But for the sake of the question let's assume that this makes sense. 但是为了这个问题,让我们假设这是有道理的。 So essentially you would have now a relation fruit_compatible/2 : 因此,基本上,您现在将拥有一个fruit_compatible/2关系:

fruit_compatible(F, G) :-
   fruit(F, _, _),
   may_coexist(F, G),
   fruit(G, _, _).  % maybe you want to add this?

And now, let's assume you want this list too. 现在,假设您也需要此列表。 So you would have a relation fruit_suggestions/2 . 因此,您将拥有一个fruit_suggestions/2关系。 How to use it? 如何使用它?

?- fruit_suggestions(apple, L).
L = [cherry, pear].

or ... should it be rather L = [pear, cherry] ? 还是...应该是L = [pear, cherry] Or both? 或两者?

?- fruit_suggestions(lemon, L).
L = [orange].

So every time I want a suggestion I have to think of a fruit. 因此,每当我想要一个建议时,我都必须想到一个水果。 Always thinking: what fruit should it be? 一直在想:那应该是什么水果? Fortunately there is a less demanding way in Prolog: Simply use a variable instead of the fruit! 幸运的是,Prolog中的要求较低:只需使用变量而不是结果! Now we should get all suggestions at once! 现在,我们应该立即获得所有建议!

?- fruit_suggestions(F, L).
F = apple, L = [cherry, pear] ;
F = lemon, L = [orange] ;
F = cromulon, L = [embiggy, mushfruit].

So we need to implement it such that it will behave that way. 因此,我们需要实现它,使其表现出这种方式。 findall/3 alone does not solve this. 单独使用findall/3并不能解决这个问题。 And implementing it manually is far from trivial. 手动实施它并非易事。 But there is setof/3 which handles variables in exactly that manner. 但是有setof/3正是以这种方式处理变量。 Many of the tiny nitty-gritty design decisions have already been made, like that the list will be sorted ascendingly. 许多细微的细节设计决定已经做出,就像清单将按升序排列一样。

fruit_suggestions(F, L) :-
   setof(G, fruit_compatible(F, G), L).

Edit: Due to the discussion below, here would be a solution that also permits empty lists. 编辑:由于下面的讨论,这将是一个允许空列表的解决方案。 Note that this sounds trivial but it is not. 请注意,这听起来微不足道,但事实并非如此。 To see this, consider the query: 要查看此信息,请考虑以下查询:

?- fruit_suggestions(F, []).

What does it mean? 这是什么意思? What should F be? F应该是什么? Also things that are no fruits at all? 那些根本没有结果的东西吗? In that case we would have to produce solutions for everything . 在这种情况下,我们将不得不为所有问题提供解决方案。 Like F = badger ; F = 42 ; ... F = badger ; F = 42 ; ... F = badger ; F = 42 ; ... F = badger ; F = 42 ; ... . F = badger ; F = 42 ; ... Most probably this does not make much sense. 这很可能没有多大意义。 What might be intended is those fruits that are incompatible with everything. 可能想要的是与所有事物都不兼容的那些水果。 To this end, we need to add a new rule: 为此,我们需要添加一个新规则:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM