Prolog:检查列表中每个项目的谓词

时间:2018-03-27 03:50:51

标签: recursion prolog

基本上,我希望能够检查列表中是否至少有一个值满足某个谓词。

到目前为止我所拥有的:

need(x,y).
check_list(X,[H|T]) :- 
   need(H,X).

所以只要我在列表中只有一个值,这样就可以正常工作。我不确定如何检查其他值。当我尝试使用递归时,我最终找到一个满足第二个谓词的元素,但它然后返回堆栈,这最终会导致它为假。我怎么能让它“打破”?

3 个答案:

答案 0 :(得分:1)

您可以使用简单的递归:

need(x,y).
check_list(X,[H|T]) :- 
   ( need(H,X) -> true; 
     check_list(X,T) ).

您可以在下面的示例中看到此定义是确定性的:

?- check_list(y,[1,2,3]).
false.

?- check_list(y,[x,2,3]).
true.

?- check_list(y,[1,2,x]).
true.

?- check_list(Y,[1,2,x]).
Y = y.

?- check_list(Y,[1,2,3]).
false.

?- check_list(Y,[1,x,3]).
Y = y.

?- check_list(Y,[1,X,3]).
Y = y,
X = x.

?- check_list(Y,[1,2,3]), Y = x.
false.

?- check_list(Y,[1,2,3]), Y = y.
false.

?- check_list(Y,[1,2,3]).
false.

?- check_list(Y,[1,2,x]), Y = y.
Y = y.

虽然您希望查询包含未经实例化的变量,例如check_list(Y,[1,2,x]).,但您添加了另一个事实need(x,z).然后:

?- check_list(Y,[1,2,x]).
Y = y.

只返回一个结果,而不是Y = z。如果您想更好地定义if_/3,可以使用库 reif 中的 check_list/3

答案 1 :(得分:1)

您在递归期间看到的回溯是Prolog试图找到更多方法让谓词成功。这是Prolog的一个基本行为,也是它有用的原因。它试图找到所有的解决方案。

在您的情况下,您只想确认一个问题的解决方案,列表中符合特定标准的元素。为此,您可以使用剪切:

check_list(X, [H|_]) :-
    need(X, H), !.    % Don't backtrack after success
check_list(X, [_|T]) :-
    check_list(X, T).

或者您可以使用once/1专门用于处理您只需要一个解决方案的案例:

check_list(X, [H|_]) :-
    need(X, H).
check_list(X, [_|T]) :-
    check_list(X, T).

check_list_once(X, L) :- once(check_list(X, L)).

答案 2 :(得分:0)

以下是您可以执行的操作的示例。 我想检查数字是否奇怪。

is_even(X) :-
   X mod 2 =:= 0.

check_list(L, CL) :-
    include(is_even, L, CL).

结果

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

?- check_list([1,3,5], L).
L = [].