我目前正在开发一个关于Prolog的非常短的项目,并且试图将我创建的“过滤器”应用到列表中。我有你可以称之为过滤器的东西,但我无法应用它。如果我说明一下会更好:
filter(A, B)
...如果满足某些条件,则输出'true'。
filterList(A, [X, Y, Z])
...输出一个列表,其中包含第二个参数中的所有元素,这些元素使过滤器输出 false 。 (因此,如果过滤器(A,X)为真,则输出为[Y,Z])。
我已准备好“过滤器”功能,但现在我需要将它应用于第二个示例中所示的列表,排除在应用第一个参数时过滤器返回true的所有元素。
所以,如果过滤器是一个简单的A == B,该函数应该接收A [A,B,A,C,D,A]并输出[B,C,D],已经删除了所有的显然,过滤器适用的元素。
我遇到了函数的基本结构问题,所以如果有人能为这样的函数提供基本的大纲,那将会有很大的帮助。我尽可能地简化了我的情况,所以我可以根据自己的需要采取任何你能提供的东西并进行修改。
提前致谢!
答案 0 :(得分:11)
如果您正在Prolog中搜索高阶函数,您应该明确地咨询Naish (1995),这是一个非常好的资源。
他对filter/3
的定义如下(他使用差异列表表示法,因此不必定义filter/4
):
filter(_,[],[]).
filter(P, A0-As0, As) :-
(
call(P, A0) -> As = A0-As1
;
As = As1
)
, filter(P, As0, As1).
我对这个谓词有疑问,请在评论中问我。强烈建议阅读该论文,同时也要谨慎map
,foldr
和compose
!请注意,他提到的许多限制(例如,丢失的call/3
或更高级的apply
不再适用.SWI-Prolog有=..
运算符,它解决了所有问题他的担忧并使任意n阶逻辑成为可能。
答案 1 :(得分:10)
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].
答案 2 :(得分:3)
过滤函数存在一个固有的问题,它将谓词的成功或失败作为过滤的标准:结果程序不再是纯粹的单调程序。因此它失去了所有的陈述性属性 - 剩下的唯一含义是程序性的逐步解释。以下是使用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).
第一个参数因此是一个闭包/继续,它将接收另外两个参数:元素和结果真值。
=(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
的标准来过滤两个元素的列表。每个元素可能相同或可能不同。
这种方法的缺点是必须提供所有标准的具体版本。
答案 3 :(得分:0)
嗯,你知道我刚才弄清楚了。所以,我在这里提交了一个自己问题的答案,正如预期的那样,一个非常短的函数完成了这项工作:
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.
).
答案 4 :(得分:0)
我得到了一个国家的成年人// 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)
这是prolog中的过滤器// Asi es un filter en prolog
答案 5 :(得分:0)
filter(_,[],[]).
filter(Predicate,[First|Rest],[First|Tail]) :-
filter(Predicate,Rest,Tail).
filter(Predicate,[_|Rest],Result) :-
filter(Predicate,Rest,Result).