基本上,我希望能够检查列表中是否至少有一个值满足某个谓词。
到目前为止我所拥有的:
need(x,y).
check_list(X,[H|T]) :-
need(H,X).
所以只要我在列表中只有一个值,这样就可以正常工作。我不确定如何检查其他值。当我尝试使用递归时,我最终找到一个满足第二个谓词的元素,但它然后返回堆栈,这最终会导致它为假。我怎么能让它“打破”?
答案 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 = [].