我最初迭代了Dictionary
:
myDictionary |> Seq.iter (fun kvp -> doSomething kvp.Key kvp.Value)
后来,我发现我可以使用KeyValue
活动模式,并执行此操作:
myDictionary |> Seq.iter (fun (KeyValue (k, v)) -> doSomething k v)
知道活动模式不是某种形式的预处理器指令,我如何能够将lambda中的kvp
参数替换为分解它的函数?
答案 0 :(得分:15)
函数参数调用总是使用模式匹配进行解构。例如:
let getSingleton = fun [x] -> x
let getFirst = fun (a,b) -> a
let failIfNotOne = fun 1 -> ()
let failIfNeitherOne = fun (x,1 | 1,x) -> ()
从语义上讲,fun
< pat> ->
< body>大致相当于
fun x ->
match x with
|
< pat> ->
< body>
| _ -> raise MatchFailureException(...)
答案 1 :(得分:6)
我认为@kvb的答案涵盖了足够的细节,为什么你可以在fun
的参数中使用模式。这不是一个临时功能 - 在F#中,您可以在任何可以绑定变量的地方使用模式。在另一个上下文中显示@kvb的一些示例:
// 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
同样,您可以在撰写fun
时使用模式。 match
构造更强大,因为您可以指定多个子句。
现在,活跃的模式并不是那么神奇。它们只是具有特殊名称的普通函数。编译器在找到命名模式时在范围内搜索活动模式。例如,您使用的模式只是一个函数:
val (|KeyValue|) : KeyValuePair<'a,'b> -> 'a * 'b
模式将KevValuePair
对象转换为普通的F#元组,然后由嵌套模式(k, v)
匹配(将第一个元素分配给k
,将第二个元素分配给{{1} }})。编译器实际上将您的代码翻译为:
v