如何在退出之前获得检查所有条件的规则?

时间:2017-03-29 10:56:23

标签: prolog

我正在尝试编写一个带有weird_sum(List, Result)个数字的谓词List,并计算列表中大于或等于5的数字的平方和,减去小于或等于2的数字的绝对值之和。例如:

?- weird_sum([3,6,2,-1], Result).
Result = 33 

那是6×6 - 2 - 1.

我正在尝试使用两个条件来检查数字是>= 5还是<= 2。但每当我调用谓词“computerResult”时,它只会检查第一个条件并退出。它永远不会达到第二个条件。如果第一个条件失败,如何检查第二个条件?

这是我的代码:

%base case
weird_sum([], 0).       

%figuring out if number is large or small
computeResult(Head, Result + Head*Head):-
    Head >= 5.

computeResult(Head, Result - abs(Head)):-
    Head @=< 2.

%recursive case
weird_sum([Head|Tail], Result):-
    weird_sum(Tail, Result),
    computeResult(Head,Result).

1 个答案:

答案 0 :(得分:0)

问题不在于它不会尝试第二个子句。问题是computeResult/2谓词中的第二个参数。您编写Result + Head*Head等等,这意味着Prolog将尝试统一一个数字0,其格式为+(Result,*(Head,Head)),这显然会失败。

但您可以轻松修改结果,如:

%base case
weird_sum([], 0).
%recursive case
weird_sum([Head|Tail], Result) :-
    weird_sum(Tail, SubResult),
    computeResult(Head,Adder),
    Result is SubResult+Adder.   

%figuring out if number is large or small
computeResult(Head, Head*Head):-
    Head >= 5.
computeResult(Head, -abs(Head)):-
    Head =< 2.
computeResult(Head, 0) :-
    Head < 5,
    Head > 2.

您还可以将剪切!)添加到条件中,以防止回溯computeResult/2子句。在这种情况下,您可以省略最后一句中的检查。

%figuring out if number is large or small
computeResult(Head, Head*Head):-
    Head >= 5,
    !.
computeResult(Head, -abs(Head)):-
    Head =< 2,
    !.
computeResult(_, 0).

然而,使用累加器更有效,例如:

weird_sum(List, Result) :-
    weird_sum(List, 0, Result).

weird_sum([], Result, Result).
weird_sum([Head|Tail], SubResult, Result) :-
    computeResult(Head,Adder),
    SubResult2 is SubResult+Adder,
    weird_sum(Tail, SubResult2, Result).