序言:过滤列表?
我目前正在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 map
, foldr
和compose
! 请注意,他提到的许多限制(比如缺失的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