5

F# で let バインディングに対して直接パターン マッチすることは可能ですか?

たとえば、これは警告なしでコンパイルされます。

    let value = 
        match arg with
        | 1 -> "value1"
        | 2 -> "value2"
        | _ -> failwith "key not found"

次の例では、 and に一致する行に対して「このルールは決して一致しません」という警告が表示されますkey2_

    let key1 = 1
    let key2 = 2
    let value = 
        match arg with
        | key1 -> "value1"
        | key2 -> "value2"
        | _ -> failwith "key not found"

これは、let バインディングは不変ですが、C#const変数とは異なるためでしょうか?

4

4 に答える 4

6

このエラーが発生する理由は、一致式のパターン句で変数名を使用するときに F# が行っていることです。

私が持っているとしましょう

match arg with
| x when x = 0 -> "zero"
| y when y = 1 -> "one"
| _ -> "other"

一致する前に x または y を定義していなくても、このコードは機能することに注意することがここで重要だと思います。これは、x と y がマッチ式の記述を容易にする単なる短いコードであるためです。舞台裏で、F# コンパイラは実際にそれx when x = 0を "let バインディング"に変換しxていargます。 その後、式および の後の式でx使用できます。x = 0->

遭遇した問題に戻ります。

let key1 = 1
let key2 = 2
let value = 
    match arg with
    | key1 -> "value1"
    | key2 -> "value2"
    | _ -> failwith "key not found"

これが機能しない理由は、一致式で F# がkey1の値に再バインドされているargためです。したがってkey1 -> "value1" is equivalent to、arg1 = arg1 の場合は "value1". 最初のパターンは常に一致します。そのため、決して到達することはありませんkey2_

私の説明がどれほど明確かはわかりません。そのため、何が起こったのかを説明するための 2 番目のアプローチも投入します。

一致式を if-else に変換すると、次のようになります。

let key1 = 1
let key2 = 2

let value = 
    if let key1 = arg in arg = key1 then
        "value1"
    else if let key2 = arg in arg = key2 then
        "value2"
    else
        failwith "key not found"

(そうです。F# では、let バインディングを if 式にスローできます)

この if/else 式は、一致式と同等です。この形式では、最初の条件が常に true と評価されることが明らかになります。

ここには入れませんが、一致式のコード クォーテーションを参照すると役立つ場合があります。生成された抽象構文ツリーがどのように見えるかを見るまで、マッチ式で何が起こっているのかを実際に理解することはできませんでした。

于 2014-03-15T19:55:49.913 に答える
6

大文字と[<Literal>]それらを使用するだけで、期待どおりに機能します。

let [<Literal>] X = 0
let [<Literal>] Y = 1
let bla arg =
    match arg with
    | X -> "zero"
    | Y -> "one"
    | somethingelse -> somethingelse.ToString()

通常、慣例により小文字の名前は、名前にバインドされたワイルドカードを意味します。

于 2014-03-15T15:08:57.607 に答える
2

パターン マッチング ケースで特定の値と照合する場合にのみ、リテラルを使用できます。識別子はバインドを意味します。つまり、このパターン マッチング ケースの実際の値は、このケースのスコープで表示される識別子にバインドされます。

@DanielFabian が示したように、独自のリテラルを定義して名前を付けることができます。

照合する必要がある値がコンパイル時に不明な場合は、次のようにガードを使用できます。

match arg with
| x when x = key1 -> "value1"
| x when x = key2 -> "value2"
| _ -> // etc

詳細については、パターン マッチングに関する MSDN の記事を参照してください。

于 2014-03-15T16:42:20.473 に答える