2013-09-07 12 views
5

Mam dziwne doświadczenie z funkcją filtru F # już dziś. Kod jest:F # funkcja filtru - warunek pierwszego argumentu wydaje się być odwrócony

let rec filter : ('a -> bool) -> 'a list -> 'a list = 
    fun isKept -> function 
     | [] -> [] 
     | (x::xs) -> if isKept x then x::filter isKept xs 
        else filter isKept xs 

let x = filter ((>) 1) [1; -5; -20; 30; -35; 40] 

Ten kod zwraca

val x : int list = [-5; -20; -35] 

Problem jest, jak mijam warunek w pierwszym argumencie (> 1), spodziewam się, że to odfiltrować żadnych elementów lista sekundę argument, który jest większy 1, a nie odwrotnie.

Czy jest coś oczywistego, czego nie mogłem zauważyć?

Odpowiedz

6

Twoja funkcja filtra jest w porządku. Problemem jest to, że ta linia kodu:

let x = filter ((>) 1) [1; -5; -20; 30; -35; 40] 

jest równoznaczne z tym kodem, jeśli używasz jawne lambda zamiast częściowo stosowania operatora (>):

let x = filter (fun x -> 1 > x) [1; -5; -20; 30; -35; 40] 

Powodem tego jest to, że (>) funkcja przyjmuje dwa argumenty; chociaż 1 pojawia się na prawo od (>), to nie jest przekazywane jako "prawy" argument funkcji. Rozwiązaniem jest albo użyć (<) zamiast:

> let x = filter ((<) 1) [1; -5; -20; 30; -35; 40];; 

val x : int list = [30; 40] 

lub używać wyraźnej funkcji lambda, aby zapewnić stosowanie argumentów w odpowiedniej kolejności:

> let x = filter (fun x -> x > 1) [1; -5; -20; 30; -35; 40];; 

val x : int list = [30; 40] 
+0

Piękny, dzięki;) – user2431438

+0

pamiętać, że uzupełnienie '(>)' nie jest '(<)' ale '(<=)'. – Frank

+1

@Frank Masz rację - ale pytanie brzmi "Oczekuję, że odfiltrowałoby jakiekolwiek elementy listy drugiego argumentu, które są większe niż [1]". Więc '(<)' jest potrzebne, aby uzyskać poprawny wynik. –

Powiązane problemy