6

我使用以下失败驱动循环来列出所有内容而不使用分号。

happiness(fred,5).
happiness(john,3).
happiness(grace,2).

someGoal(X) :-
        happiness(X,Y), write(Y), tab(4), fail.

在查询模式下,我得到了预期

?- someGoal(_).
5    3    2 

如何将这些数字插入列表而不是将它们写入屏幕?我无法在内部处理这个问题,someGoal因为回溯似乎是隐含的。

4

2 回答 2

6

你是对的,回溯它是 Prolog 处理替代方案的方式。

使用findall /3,它使用“内部”回溯收集所有备选方案:

someGoal(X, Values) :-
    findall(Value, happiness(X, Value), Values).

然后?- someGoal(_, Values).将实例 Values = [5, 3, 2]

于 2012-10-24T20:54:13.330 回答
5

故障驱动的循环通常会使某些部分处于打开状态且未指定,迟早会导致一些问题。特别是变量的精确量化很容易保持开放。通常,这样的循环可以完全避免。在你的例子中,我不清楚你为什么要争论someGoal/1。至少你不使用它。于是出现了几个问题:

  1. 如果没有匹配的值,你期望什么?您的原始程序不打印任何内容并且失败。

  2. 如果有多余的条目,您会期望什么?你想把东西打印几次吗?

  3. 你坚持价值的精确顺序,还是你能想象另一个顺序?

  4. 你为什么对看到这些价值观感兴趣?大多数时候,您要么希望将它们与具体名称相关联,要么希望将其聚合,例如总和或平均值。

鉴于我不知道这些问题的答案,我可以为您提供几种解决方案。我将以一个额外的(冗余)事实为例:

幸福(弗雷德,5)。
幸福(约翰,3)。
幸福(约翰,3)。
幸福(恩典,2)。

?- setof(PH,happiness(P,H), PHs)。
PHs = [fred-5,grace-2,john-3]。

?- setof(H,P^happiness(P,H), PHs)。
PH = [2, 3, 5]。

?- bagof(H,P^happiness(P,H), PHs)。
PH = [5, 3, 3, 2]。
于 2012-10-25T14:50:24.473 回答