2008-11-18 13 views
15

Obecnie pracuję nad bardzo krótkim projektem na Prologu i po prostu utknąłem próbując zastosować "filtr", który stworzyłem do listy. Mam gotowy filtr, ale nie mogę go zastosować. Byłoby lepiej, gdybym zilustrował:Prolog: Filtrowanie listy?

filter(A, B) 

... wyświetla "true", jeśli spełnione są określone warunki.

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

... generuje listę, która zawiera wszystkie elementy z drugiego argumentu, że ich wyjścia filtra fałszywy. (Jeśli więc filtr (A, X) jest prawdziwy, wyjście to [Y, Z]).

Mam funkcję "filtra", ale teraz muszę zastosować ją do listy, jak pokazano w drugim przykładzie, z wyłączeniem wszystkich elementów, dla których filtr zwraca wartość true, gdy zostanie zastosowany z pierwszym argumentem.

Tak więc, jeśli filtr jest prosty A == B, funkcja ma otrzymać A [A, B, A, C, D, A] i wyjście [B, C, D], po usunięciu wszystkich elementy, dla których stosuje się filtr, oczywiście.

Mam problem z podstawową strukturą funkcji, więc jeśli ktoś mógłby podać podstawowy zarys funkcji takiej jak ta, byłby bardzo pomocny. Uprościliśmy moją sytuację tak bardzo, jak to tylko możliwe, aby móc wziąć wszystko, co tylko możesz, i zmodyfikować ją dla moich potrzeb.

Z góry dziękuję!

Odpowiedz

11

Jeśli szukasz funkcji wyższego rzędu w Prologu, należy na pewno skonsultować Naish (1995), bardzo dobry zasoby na ten temat.

Jego definicja filter/3 jest następujący (używa różnica-lista notacja, dlatego ucieka konieczności definiowania filter/4):


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

I masz pytania dotyczące tego predykatu, proszę zapytać mnie w komentarzu . Bardzo zalecane jest również czytanie papieru, a także defensywność: map, foldr i compose! Zauważ, że wiele ograniczeń, o których wspomniał (np. Brakujący call/3 lub wyższego rzędu apply, już nie obowiązuje. SWI-Prolog ma operatora =.., który adresuje wszystkie swoje obawy i umożliwia dowolną logikę n-tego porządku.

+1

Pitty Naish proponuje zastosowanie/3 w swoich wnioskach, ale domyślam się, że obecnie należy użyć call/n. apply/3 to po prostu wywołanie/3. –

+2

Zobacz dyskusję, dlaczego Naish Reference jest kwestionowany: http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/naish.html –

0

Cóż, wiesz, po prostu to wymyśliłem. Tak więc, oto ja składania odpowiedzi na moje własne pytanie, zgodnie z oczekiwaniami bardzo krótko funkcję spełniała zadanie:

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

Ta wersja zawsze odnosi sukces na dowolnej liście. Zamierzony? – false

7

SWI-Prolog oferuje exclude/3 i inne tego typu meta-orzeczników pierwotny problem może być zakodowany tak:. przykład

are_identical(X, Y) :- 
    X == Y. 

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

Zastosowanie:

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

include (<(5), [3,4,5,6 , 7], As). działa tak samo jak filtr (<(5), [3,4,5,6,7], As). exclude jest odwrotnością, ponieważ daje takie same wyniki jak filtr (> = (5), [3,4,5,6,7], As). – joeblog

3

Istnieje nieodłączny problem z funkcjami filtra, które odnoszą sukces lub porażkę predykatu jako kryterium filtrowania: Wynikowy program nie jest już czystym monotonicznym programem. W związku z tym traci wszystkie swoje deklaratywne właściwości, jedyne znaczenie, jakie pozostaje, to proceduralna interpretacja krok po kroku.Oto czysta, reified wersja filtrowanie za pomocą 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). 

Pierwszy argument jest więc zamknięcie/kontynuacja że otrzyma dwa kolejne argumenty: element i uzyskaną wartość prawda.

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

Teraz wyniki są dokładne:

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

Istnieją cztery możliwości jak lista dwa elementy mogą być filtrowane według kryterium jest równa X. Każdy element może być równy lub inny.

Wadą tego podejścia jest to, że należy podać reifikowane wersje wszystkich kryteriów.

0

dostaję dorosłych z kraju // Obtengo los Dorosłych de un Pais, Kraj = Pais, Ludzie = Personas, Osoba = una sola Persona

habitants(USA, [juan, pedro, david]) 

adults(Adults, Country) :- 
    findall(Person, (habitants(Country,People), member(People, Person), adult(Person)), Adults) 

Jest to filtr w prolog // Asi es un filter en prolog