1

通常の関数をパターンとして使用できれば、次のような簡単なアクティブパターンを作成する必要がなくなります。

let (|NotEmpty|_|) s = Seq.tryPick Some s

そして、仮想的に、許可します

let s = seq []
match s with
| Seq.tryPick Some -> ...
| _ -> //empty

これにより、関数がより再利用可能になり、マッチングで使用する「パターン化」関数が不要になります。

let f x = if x then Some() else None
let (|F|_|) = f

アクティブなパターンは関数として呼び出される可能性があることを知っているので、前の例はパターンのみを定義することで簡略化できます。ただし、特別なパターン構文を使用しないと、これが簡単になります。

特別な構文の理由は何ですか?

編集

以下では、アクティブなパターンがリテラルをシャドウイングします。

[<Literal>]
let X = 1
let (|X|_|) x = if x = 0 then Some() else None

match 0 with //returns true
| X -> true
| _ -> false

パターン内の関数呼び出しでも機能しないのはなぜですか?

編集2

あいまいなシナリオを見つけました

let zero n = if n = 0 then Some() else None
match 0 with
| zero -> //function call or capture?

これは、私の考えでは、アクティブなパターンが大文字で始まらなければならない理由を明確にします。これにより、意図が明確になり、前の例のようにシャドウイングが発生する可能性がはるかに低くなります。

4

2 に答える 2

5

この質問に答える 1 つの方法は、アクティブなパターン (特別な構文カテゴリとして) を使用すると、式で値を構築し、パターンでそれを分解するために同じ名前を使用できるようになるということです。

たとえば、Infoある情報を表すために型を使用しているとしましょう。

type Info = I of string * int

この型の値を構築および破棄する 2 つの関数を記述できます。

val constructInfo : string * int -> Info
val destructInfo  : Info -> string * int

この場合、2 つの関数を実装するのは簡単ですが、興味深い点は、それらの型シグネチャが二重であることです。構築は値を取り、(抽象) 型を作成し、破壊は型を取り、個々の値を返します。

アクティブなパターンを使用すると、Info両方の目的で同じ名前 を使用できます。これにより、言語の残りの部分と一貫性が保たれます。たとえばx::xs、 and(a, b)はコンストラクターとパターンの両方です。F# ライブラリは、F# クォートに対して同様のことを行います (つまりLambda、 type のパターンとコンストラクタの両方Exprです。

したがって、construct関数とdestruct関数を記述する代わりに、関数とパターンを定義できます。

let Info (a, b) = I (a, b)
let (|Info|) (I (a, b)) = (a, b)

その結果、同じ構文 がInfo(a, b)パターンと式の両方として表示される可能性があります。

于 2011-11-14T22:30:49.817 に答える
1

パターンと自由変数は異なる名前空間を持っています。これは、シャドウイングが発生する頻度と短い識別子が使用される頻度を考えると、ほとんどの場合意味があります。たとえば、xプログラムの1行目で定義し、200行後にはを定義する場合がありmatch ... with | (x,y) -> x + yます。この場合、ほぼ確実xに新しい識別子になります。

任意の関数を使用する場合は、パラメーター化されたアクティブパターンを使用するだけです。

let (|Id|_|) f x = f x

match seq [] with
| Id (Seq.tryPick Some) _ -> ...

編集

名前解決の詳細については、仕様のパターンの名前解決を参照してください。重要なのは、式の名前に使用されるExprItemsテーブルとは異なる論理PatItemsテーブルがあることです。質問の編集に追加した特定のケースでは、最後の定義が優先されるため、この場合はアクティブなパターンとして扱われます(パターンに表示されるときに文字を効果的にシャドウイングします)。XX

名前の衝突/シャドウイングの問題に加えて、パターンでより広い範囲の表現を許可すると、手に負えないものは考えられませんが、あいまいな解析が発生する方法もあると思います。

于 2011-11-14T18:55:03.763 に答える