9

Dictionary私は最初にこうして繰り返したオーバーを持っています:

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

後で、KeyValueアクティブなパターンを利用できることを発見し、これを実行します。

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

アクティブなパターンが何らかの形式のプリプロセッサディレクティブではないことを知っているのでkvp、ラムダの引数を、それを分解する関数に置き換えるにはどうすればよいですか?

4

2 に答える 2

16

関数の引数呼び出しは、常にパターン マッチングを使用して構造化解除されます。例えば:

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
|<パット> -><ボディ>
| _ -> raise MatchFailureException(...)

于 2012-11-27T18:16:52.213 に答える
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# タプルに変換し、ネストされたパターン(最初の要素をに、2 番目の(k, v)要素を に割り当てます) と照合します。コンパイラは基本的にコードを次のように変換します。kv

myDictionary |> Seq.iter (fun _arg0 ->
  let _arg1 = (|KeyValue|) _arg0
  let (k, v) = _arg1 
  doSomething k v )
于 2012-11-27T18:43:25.190 に答える