将列表元素与谓词进行比较

Comparing list elements to a predicate

我需要构造一个谓词compare_to_predicate/3。它接受给定的谓词和数字列表,并使用该谓词继续比较列表中的每个元素。
给定的谓词是
- is_odd
- is_even
- greater_than(X)
例如:

?- compare_to_predicate([8,13,1,500], [is_odd], X).
X = [13, 1].
?- compare_to_predicate([8,13,1,500], [greater_than, 10], X).
X = [13, 500].  

到目前为止我想出的是:

is_odd(X):- 1 is mod(X,2).
is_even(X):- 0 is mod(X,2).
greater_than(X,Y):- X<Y.
compare_to_predicate([],_,[]).
compare_to_predicate([H|Tail],Functor,[H|X]):- Term =.. [Functor,H], Term, compare_to_predicate(Tail,Functor,X).  

我有很多问题:

1)

?- compare_to_predicate([2,10,8,300],is_even,X).

会产生

X = [2, 10, 8, 300].

但是

compare_to_predicate([2,10,8,301],is_even,X).

会产生

false.

我假设它与谓词遇到一个数字有关,该数字在 is_even 上不会 return 为真,然后以假终止整个 compare_to_predicate。在那种情况下,解决方案是以某种方式使其忽略奇数而不是评估它们吗?如果是这样,我该怎么做?

2)

似乎我传递给 compare_to_predicate 的给定谓词必须具有

中看到的类型列表
?- compare_to_predicate([8,13,1,500], [is_odd], X). 

?- compare_to_predicate([8,13,1,500], [greater_than, 10], X).  

我目前只是将一个普通的谓词传递到术语中。我不太确定我应该怎么做
好像compare_to_predicate([H|Tail],[Functor],[H|X]):- Term =.. [Functor,H], Term, compare_to_predicate(Tail,[Functor],X)
在这里做了把戏。最后:

3)

?- compare_to_predicate([8,13,1,500], [greater_than, 10], X).

看来我需要让 compare_to_predicate 能够接收具有不同数量的谓词,如此处所示。解决方案应该是这样的吗?

(Term =.. [Functor,A]; Term=.. [Functor,A,B]).  

任何帮助将不胜感激。

您需要决定 compare_to_predicate/3 应该如何处理未达到目标的值。我基本上看到了三种方式:

  1. 它可以作为一个过滤器,第三个参数与第一个参数中通过的值统一。
  2. 它可以表现为一个 for-all,如果全部通过则第三个参数与整个列表统一,否则失败(您当前的行为)
  3. 它可以像 for-each 一样运行,只是将谓词应用于列表中的每个项目并丢弃结果。在这种情况下,第三个参数没有有意义的值。

顺便说一句,您在 =../2 中进行的术语手术是不必要的; call/N 将做正确的事情,如果你做类似 call(greater(10), 20) 的事情,所以你可以只允许用户像这样调用你的谓词:compare_to_predicate([1,2,3,4], greater(2), X) 并使用 call 来构建目标。

做第一个非常简单:

filter([], _, []).
filter([X|Xs], P, Result) :-
    filter(Xs, P, Xs1),
    (call(P, X) -> Result = [X|Xs1] ; Result = Xs1).

做第二个也很简单:

forall([], _, []).
forall([X|Xs], P, [X|Xs]) :- call(P, X), forall(Xs, P, Xs).

做第三个并不难:

foreach([], _).
foreach([X|Xs], G) :- once(call(G, X) ; true), foreach(Xs, G).