2013-09-07 66 views
5

Tôi có một chút kinh nghiệm lạ với chức năng lọc F # hôm nay. Mã này là:Chức năng lọc F # - điều kiện của đối số đầu tiên dường như bị đảo ngược

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] 

Đó là mã trả về

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

Vấn đề là, như tôi đã vượt qua một điều kiện trong đối số đầu tiên (> 1), tôi hy vọng nó sẽ lọc ra bất kỳ yếu tố danh sách thứ hai đối số lớn hơn 1, không phải ngược lại.

Có điều gì rõ ràng là tôi không thể phát hiện được không?

Trả lời

6

Chức năng lọc của bạn vẫn ổn. Vấn đề là dòng mã này:

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

là tương đương với mã này nếu bạn sử dụng một lambda rõ ràng thay vì áp dụng một phần các (>) điều hành:

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

Lý do cho điều này là các (>) hàm nhận hai đối số; mặc dù 1 xuất hiện ở bên phải của (>), nhưng nó không được chuyển thành đối số "đúng" cho hàm. Giải pháp là để thể sử dụng (<) thay vì:

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

val x : int list = [30; 40] 

hoặc sử dụng một chức năng lambda rõ ràng để đảm bảo bạn áp dụng các lập luận theo đúng thứ tự:

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

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

đẹp, nhờ;) – user2431438

+0

Lưu ý rằng sự bổ sung của '(>)' không phải là '(<)' nhưng '(<=)'. – Frank

+1

@ Frank Bạn đúng - nhưng câu hỏi nêu rõ 'Tôi hy vọng nó sẽ lọc ra bất kỳ phần tử danh sách nào của đối số thứ hai lớn hơn [1]. Vì vậy, '(<)' là cần thiết để có được kết quả chính xác. –