1

我是 prolog 的新手,我已经构建了以下示例函数:

bar(Fruit) :-
   Fruit = fruit(apple, X),
   A is abs(X) + 0,
   between(0,10,A).

foo(L) :-
   findall(X, bar(fruit(apple, X)), L).

调用foo(L)给出错误:ERROR: is/2: Arguments are not sufficiently instantiated

现在,我已经阅读了多个线程,其中经常出现的解决方案是使用clpfdwhere A #= abs(X) + 0。但是,当使用该解决方案时,我不一定会得到我想要的列表:

L = [0, _G9407, _G9410, _G9413, _G9416, _G9419, _G9422, _G9425, _G9428|...],
clpfd:in(_G9407, -1\/1),
clpfd:in(_G9410, -2\/2),
clpfd:in(_G9413, -3\/3),
clpfd:in(_G9416, -4\/4),
clpfd:in(_G9419, -5\/5),
clpfd:in(_G9422, -6\/6),
clpfd:in(_G9425, -7\/7),
clpfd:in(_G9428, -8\/8),
clpfd:in(_G9431, -9\/9),
clpfd:in(_G9434, -10\/10).

尤其是在使用更复杂的函数时,它也变得非常难以阅读。我期待的输出本质上是一个清晰而简单的列表: [-10...10]如果没有 clpfd,还有其他选择吗?我还通过这个过程了解到,我使用逻辑运算符得到了类似的错误,例如<, >, >=, =<which pushes me to use between。我来自 OOP 背景,我很难理解逻辑缺陷是什么。

谢谢您的帮助,

4

1 回答 1

1

Prolog 主要是关系型的,因为您通常可以在两个方向上进行计算,但不能用数学计算。is/2要求 RHS 是一个值(没有未实例化的变量)。而且您不能同时使用abs(X)+X 和 -X,这似乎是您所期望的。+ 0没用,但我猜你只是从其他东西简化了。

这有效:

bar(Fruit) :-
  Fruit = fruit(apple, X),
  between(0,5,A),
  ( X = A ; X is -A ).

给予

?- foo(L).
L = [0, 0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5].

但听起来你可能想使用 CLP(FD) 来做你想做的事。

于 2018-04-20T14:59:18.587 回答