序言:过滤列表?

我目前正在Prolog的一个非常短的项目上工作,只是试图将我创build的“filter”应用到列表中。 我有你可以称之为filter准备好,但我不能应用它。 如果我说明会更好:

filter(A, B) 

如果满足某些条件,则输出“真”。

 filterList(A, [X, Y, Z]) 

…输出一个列表,其中包含第二个参数中使得filter输出为false的所有元素。 (所以如果filter(A,X)为真,输出是[Y,Z])。

我已经准备好了“filter”函数,但是现在我需要将它应用到第二个示例所示的列表中,排除在应用第一个参数时filter返回true的所有元素。

因此,如果filter是一个简单的A == B,函数应该接收A [A,B,A,C,D,A]并输出[B,C,D]该filter适用,显然。

我在函数的基本结构上遇到了麻烦,所以如果任何人都可以为这样的函数提供一个基本的提纲,那将是非常有帮助的。 我尽可能地简化了我的情况,以便我可以根据需要提供和修改它。

提前致谢!

如果您在Prolog中search更高级的函数,那么您应该详细地咨询Naish(1995) ,这是一个很好的资源。

他的filter/3定义如下(他使用了差异表示法,所以逃避了必须定义filter/4 ):

 filter(_,[],[]). filter(P, A0-As0, As) :- ( call(P, A0) -> As = A0-As1 ; As = As1 ) , filter(P, As0, As1). 

我对这个谓词有疑问,请在评论中问我。 读纸也强烈推荐,它也defly mapfoldrcompose ! 请注意,他提到的许多限制(比如缺失的call/3或更高阶的apply不再适用).SWI-Prolog有=..操作符,它解决了所有的问题,顺序逻辑可能。

SWI-Prolog提供了exclude/3和其他这样的元谓语。 你原来的问题可以这样编码:

 are_identical(X, Y) :- X == Y. filterList(A, In, Out) :- exclude(are_identical(A), In, Out). 

用法示例:

 ?- filterList(A, [A, B, A, C, D, A], Out). Out = [B, C, D]. 

过滤函数有一个固有的问题,它把谓词的成功或失败作为过滤的标准:结果程序不再是一个纯粹的单调程序。 因此它失去了所有的陈述性质 – 唯一的意义就是程序上的一步一步的解释。 以下是使用if_/3进行过滤的纯粹的具体化版本:

 tfilter(_CT_2, [], []). tfilter(CT_2, [E|Es], Fs0) :- if_(call(CT_2,E), Fs0 = [E|Fs], Fs0 = Fs ), tfilter(CT_2, Es, Fs). 

因此,第一个论点是closures/延续,将接受另外两个论点:元素和由此产生的真值。

 =(X,X,true). =(X,Y,false) :- dif(X,Y). 

现在,结果仍然是确切的:

 | ?- tfilter(=(X),[A,B],Xs). B = A, X = A, Xs = [A,A] ? ; X = A, Xs = [A], dif(A,B) ? ; X = B, Xs = [B], dif(B,A) ? ; Xs = [], dif(X,A), dif(X,B) ? ; no 

有四种可能性,两个元素的列表可以通过等于X的标准过滤。 每个元素可能相同或可能不同。

这种方法的缺点是必须提供所有标准的统一版本。

那么你知道我刚才知道了什么。 所以,这里是我提出一个自己的问题的答案,正如所料,一个非常短的function做了这个工作:

 filterList(_,[],R,R). % Returns answer when the list is exhausted. filterList(L,[A|List],Temp,Res) :- filterList(L,List,New,Res), % Recursive call, New is either the same list ( filter(L,A), % in case the filter outputs true, or the list New = Temp ; New = [A|Temp] % plus the current element otherwise. ). 

我得到了一个国家的成年人// Obtengo los adultos de un pais,Country = Pais,People = Personas,Person = una sola Persona

 habitants(USA, [juan, pedro, david]) adults(Adults, Country) :- findall(Person, (habitants(Country,People), member(People, Person), adult(Person)), Adults) 

这是序言中的一个filter// Asi es un filter en prolog