2012-11-27 32 views
7

Tôi có một Dictionary qua mà tôi ban đầu lặp thusly:Đang cố gắng để hiểu F # mô hình hoạt động, lý do tại sao tôi có thể làm điều này:

myDictionary |> Seq.iter (fun kvp -> doSomething kvp.Key kvp.Value)

Sau đó, tôi phát hiện ra rằng tôi có thể tận dụng các mô hình hoạt động KeyValue , và làm điều này:

myDictionary |> Seq.iter (fun (KeyValue (k, v)) -> doSomething k v)

Biết rằng mô hình hoạt động không phải là một số hình thức chỉ thị tiền xử lý, làm thế nào tôi có thể thay thế các kvp đối số trong lambda cho một chức năng phân hủy nó?

Trả lời

14

Đối số chức năng gọi luôn bị hủy hoại bằng cách sử dụng đối sánh mẫu. Ví dụ:

let getSingleton = fun [x] -> x 
let getFirst = fun (a,b) -> a 
let failIfNotOne = fun 1 ->() 
let failIfNeitherOne = fun (x,1 | 1,x) ->() 

Ngữ nghĩa, fun < pat>-> < body> là tương đương với

fun x ->
match x with
| < pat>-> < body>
| _ -> raise MatchFailureException(...)

+0

Cảm ơn, đây là một công cụ mở mắt, kvb! Tôi chắc chắn sẽ phải giữ ví dụ cuối cùng trong tâm trí, đặc biệt. – MiloDC

5

Tôi nghĩ rằng câu trả lời từ @kvb bao gồm đủ deta ils lý do tại sao bạn có thể sử dụng các mẫu trong các đối số của fun. Đây không phải là một tính năng đặc biệt - trong F #, bạn có thể sử dụng các mẫu ở bất kỳ nơi nào bạn có thể liên kết một biến. Để hiển thị một số ví dụ bởi @kvb trong những bối cảnh khác:

// When declaring normal functions  
let foo [it] = it // Return the value from a singleton list 
let fst (a, b) = a // Return first element of a pair 

// When assigning value to a pattern using let 
let [it] = list 
let (a, b) = pair 

Tương tự như vậy, bạn có thể sử dụng các mẫu khi viết fun. Cấu trúc match mạnh hơn một chút vì bạn có thể chỉ định nhiều mệnh đề.

Hiện tại, các mẫu hoạt động không thực sự huyền diệu. Chúng chỉ là những chức năng bình thường với những cái tên đặc biệt. Trình biên dịch tìm kiếm các mẫu hoạt động trong phạm vi khi nó tìm thấy một mẫu có tên. Ví dụ, mô hình bạn đang sử dụng chỉ là một chức năng:

val (|KeyValue|) : KeyValuePair<'a,'b> -> 'a * 'b 

Các mô hình hóa một đối tượng KevValuePair thành F # tuple bình thường mà sau đó được kết hợp bởi một mô hình lồng nhau (k, v) (mà gán các yếu tố đầu tiên để k và thứ hai đến v). Trình biên dịch về cơ bản dịch mã của bạn thành:

myDictionary |> Seq.iter (fun _arg0 -> 
    let _arg1 = (|KeyValue|) _arg0 
    let (k, v) = _arg1 
    doSomething k v) 
+4

Không hoàn toàn ở khắp mọi nơi ... Ít nhất 'sử dụng' ràng buộc và 'này' định danh trong khai báo thành viên bị hạn chế sử dụng định danh thích hợp chứ không phải là mẫu, thật đáng buồn. – kvb

+4

@kvb Đúng và đúng. Ngoài ra không cho 'như self' trong các lớp constructor ngầm định. Tôi tin rằng đây là ba trường hợp duy nhất, nơi có thực sự là một ý nghĩa cho tên. –

+1

@kvb Đó là một điểm tuyệt vời, ah tốt, cuộc xung đột giữa lý thuyết và thực hành đình công một lần nữa :-) –

Các vấn đề liên quan