我是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
。
现在,我已经阅读了多个线程,其中重复解决方案是使用clpfd
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]
。< / strong>没有clpfd有没有替代方案?我还通过这个过程了解到,使用<, >, >=, =<
之类的逻辑运算符可以使用between
来获取类似的错误。我来自OOP背景,我很难掌握逻辑上的缺陷......
感谢您的帮助,
答案 0 :(得分: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)来做你想做的事。