Prolog: Filtrando uma lista?

Atualmente estou trabalhando em um projeto muito curto no Prolog, e fiquei preso tentando aplicar um “filtro” que criei em uma lista. Eu tenho o que você poderia chamar de filtro pronto, mas não posso aplicá-lo. Seria melhor se eu ilustrasse:

filter(A, B) 

… saídas “verdadeiras” se certas condições forem atendidas.

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

… gera uma lista que inclui todos os elementos do segundo argumento que tornam a saída do filtro falsa . (Assim, se o filtro (A, X) for verdadeiro, a saída será [Y, Z]).

Eu tenho a function “filter” pronta, mas agora preciso aplicá-la a uma lista como mostrado no segundo exemplo, excluindo todos os elementos para os quais o filtro retorna true quando aplicado com o primeiro argumento.

Então, se o filtro é simples A = = B, a function deve receber A [A, B, A, C, D, A] e saída [B, C, D], tendo removido todos os elementos para os quais o filtro se aplica, obviamente.

Estou tendo problemas com a estrutura básica da function, portanto, se alguém puder fornecer um esboço básico para uma function como essa, seria de grande ajuda. Eu simplifiquei a minha situação tanto quanto possível para que eu possa levar o que você puder fornecer e modificá-lo para as minhas necessidades.

Desde já, obrigado!

    Se você está procurando por funções de ordem superior no Prolog, você deve definitivamente consultar Naish (1995) , um recurso muito bom sobre isso.

    Sua definição de filter/3 é a seguinte (ele usa notação de lista de diferenças, portanto escapa de definir filter/4 ):

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

    Eu tenho perguntas sobre este predicado, por favor, pergunte-me no comentário. Lendo o papel também é altamente recomendado, também definess map , foldr e compose ! Note que muitas das limitações que ele menciona (como, por exemplo, uma call/3 falta call/3 ou uma apply ordem superior não se aplicam mais. O SWI-Prolog tem o operador =.. , que aborda todas as suas preocupações e faz n arbitrários ordem lógica possível.

    O SWI-Prolog oferece exclude/3 e outros meta-predicados. Seu problema original pode ser codificado assim:

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

    Exemplo de uso:

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

    Existe um problema inerente às funções de filtro que levam em conta o sucesso ou a falha de um predicado como critério de filtragem: O programa resultante não é mais um programa monotônico puro. Portanto, perde todas as suas propriedades declarativas – o único significado que permanece é uma interpretação passo-a-passo processual. Aqui está uma versão pura e reificada da filtragem usando 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). 

    O primeiro argumento é, portanto, um encerramento / continuação que receberá dois argumentos adicionais: O elemento e o valor de verdade resultante.

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

    Agora, os resultados permanecem precisos:

     | ?- 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 

    Existem quatro possibilidades de como uma lista de dois elementos pode ser filtrada pelo critério de ser igual a X Cada elemento pode ser igual ou diferente.

    A desvantagem dessa abordagem é que é preciso fornecer versões reificadas de todos os critérios.

    Bem, o que você sabe, eu acabei de descobrir. Então, aqui está eu enviando uma resposta para a minha própria pergunta, como esperado, uma function realmente curta fez o trabalho:

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

    Eu obtenho os adultos de um país // Obtendo os adultos de um pais, País = Pais, Pessoas = Personas, Pessoa = una sola Persona

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

    Este é um filtro em prólogo // Asi es un filter en prolog