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

时间:2017-10-06 10:09:02

标签: list prolog 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上返回true的数字的谓词有关,然后用false结束整个compare_to_predicate。在这种情况下解决方案以某种方式使它忽略奇数而不是评估它们?如果是这样,我该怎么做?

2)

似乎我传入compare_to_predicate的给定谓词必须具有中所见的类型List

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

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

我目前只是将正常谓词传递给Term。我不太确定我应该怎么做 似乎是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能够接受具有不同arity的谓词,如此处所示。解决方案应该是这样的吗?

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

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

您需要决定compare_to_predicate/3应该对未达到目标的值做什么。我基本上可以看到三种方式:

  1. 它可以表现为过滤器,第三个参数与传递的第一个参数中的值统一。
  2. 它可以表现为一个全部,第三个参数与整个列表统一,如果它们都通过,否则失败(你当前的行为)
  3. 它的行为类似于for-each,它只是将谓词应用于列表中的每个项目并丢弃结果。在这种情况下,第三个参数没有任何有意义的值。
  4. 顺便说一句,你不需要用=../2进行手术这个术语;如果您执行call/N之类的操作,call(greater(10), 20)会做正确的事情,因此您可以让用户像这样调用您的谓词:compare_to_predicate([1,2,3,4], greater(2), X)并使用调用来构建目标。

    做第一个非常简单:

    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).