68

switch ステートメントとパターン マッチング (F#) の違いを何人かの人に説明しようとしてきましたが、うまく説明できませんでした..ほとんどの場合、彼らは私を見て「なぜif..then..else だけを使用しないでください。

彼らにどのように説明しますか。

編集!すばらしい回答をありがとうございます。複数の正解をマークできればと思います。

4

9 に答える 9

40

以前は「それらの人々」の一人でしたが、パターンマッチングがなぜこんなにおいしいのかを簡潔に要約する方法があるかどうかはわかりません。それは経験的です。

パターンマッチングを一瞥して、それが栄光のswitchステートメントだと思ったとき、代数的データ型(タプルと識別された共用体)を使用したプログラミングの経験がなく、パターンマッチングが両方であることがよくわかりませんでした。コントロールコンストラクトバインディングコンストラクト。F#でプログラミングしてきたので、ようやく「理解」できました。パターンマッチングのクールさは、関数型プログラミング言語に見られる機能の合流によるものであるため、部外者を探している人が理解するのは簡単ではありません。

言語とAPIの設計に関する2部構成の短いブログシリーズの第2部で、パターンマッチングが役立つ理由の1つの側面を要約しようとしました。パート1パート2をチェックしてください。

于 2008-10-14T04:15:07.017 に答える
36

パターンは、一致させたい値の構造を記述する小さな言語を提供します。構造は任意に深くすることができ、変数を構造化された値の一部にバインドできます。

これにより、物事を非常に簡潔に書くことができます。これは、単純なタイプの数式の微分関数などの小さな例で説明できます。

type expr =
    | Int of int
    | Var of string
    | Add of expr * expr
    | Mul of expr * expr;;

let rec d(f, x) =
    match f with
    | Var y when x=y -> Int 1
    | Int _ | Var _ -> Int 0
    | Add(f, g) -> Add(d(f, x), d(g, x))
    | Mul(f, g) -> Add(Mul(f, d(g, x)), Mul(g, d(f, x)));;

さらに、パターン マッチングは静的型の静的構造であるため、コンパイラは (i) すべてのケースをカバーしていることを確認できます (ii) どの値とも一致しない冗長な分岐を検出します (iii) 非常に効率的な実装を提供します (ジャンプなどを使用)。 )。

于 2008-10-14T07:39:46.167 に答える
16

このブログ記事からの抜粋:

パターン マッチングには、switch ステートメントやメソッド ディスパッチよりもいくつかの利点があります。

  • パターン マッチは、オブジェクトだけでなく、int、float、string、およびその他の型にも適用できます。
  • パターン マッチは、複数の異なる値に対して同時に作用することができます: 並列パターン マッチング。メソッドのディスパッチとスイッチは、「this」などの単一の値に限定されます。
  • パターンは入れ子にすることができ、任意の深さのツリーにディスパッチできます。メソッドのディスパッチとスイッチは、ネストされていない場合に限定されます。
  • or-パターンを使用すると、サブパターンを共有できます。メソッドディスパッチは、メソッドがたまたま基底クラスを共有するクラスからのものである場合にのみ共有を許可します。それ以外の場合は、共通性を手動で別の関数に分解し (名前を付けて)、すべての適切な場所から不要な関数への呼び出しを手動で挿入する必要があります。
  • パターン マッチングは、エラーをキャッチする冗長性チェックを提供します。
  • ネストされたパターン マッチや並列パターン マッチは、F# コンパイラによって最適化されます。OO に相当するものは、開発中に手動で記述し、常に手動で再最適化する必要があります。これは非常に退屈でエラーが発生しやすいため、製品品質の OO コードは比較すると非常に遅くなる傾向があります。
  • アクティブ パターンを使用すると、カスタム ディスパッチ セマンティクスを挿入できます。
于 2008-10-19T03:35:22.783 に答える
9

私の頭の上から:

  1. コンパイラは、マッチですべての可能性をカバーしていないかどうかを判断できます
  2. 試合を課題として使用できます
  3. 識別された組合がある場合、各一致は異なる「タイプ」を持つことができます
于 2008-10-14T06:44:13.750 に答える
5

スイッチは前2輪。

柄合わせは車全体です。

于 2008-10-14T22:23:31.577 に答える
5

タプルには "," があり、バリアントには Ctor 引数があります.. これらはコンストラクターであり、ものを作成します。

パターンはデストラクタであり、それらを引き裂きます。

それらは二重の概念です。

これをもっと強く言えば、タプルまたはバリアントの概念は、そのコンストラクタだけでは記述できません。デストラクタが必要であるか、作成した値が役に立たないということです。値を定義するのは、これらの二重の説明です。

一般に、コンストラクタはデータ、デストラクタは制御フローと考えられます。バリアント デストラクタは代替ブランチ (多数のうちの 1 つ) であり、タプル デストラクタは並列スレッド (多数のうちのすべて) です。

並列性は、次のような操作で明らかです

(f * g) . (h * k) = (f . h * g . k) 

関数を介した制御の流れを考えると、タプルは計算を制御の並列スレッドに分割する方法を提供します。

このように見ると、式はタプルとバリアントを組み合わせて複雑なデータ構造を作成する方法です (AST を考えてみてください)。

パターン マッチは、デストラクタを構成する方法です (ここでも AST を考えてください)。

于 2011-01-05T15:56:43.003 に答える
4

OCaml でのパターン マッチは、上で説明したいくつかの方法でより表現力豊かであることに加えて、いくつかの非常に重要な静的保証も提供します。コンパイラは、パターン マッチ ステートメントによって具現化されたケース分析が次のとおりであることを証明します。

  • 網羅的(ケースを見逃すことはありません)
  • 非冗長 (前のケースによってプリエンプトされるため、決してヒットできないケースはありません)
  • サウンド (問題のデータ型を考えると不可能なパターンはありません)

これは本当に大したことです。これは、初めてプログラムを作成するときに役立ち、プログラムが進化しているときに非常に役立ちます。適切に使用すると、match-statement を使用すると、コード内の型を確実に変更しやすくなります。これは、型システムが壊れた match ステートメントを指し示すためです。これは、修正が必要なコードがある場所の適切な指標です。

于 2009-02-08T14:54:02.017 に答える
-2

おそらく、文字列と正規表現との類似性を引き出すことができますか? 探しているものを記述し、コンパイラーにその方法を理解させます。これにより、コードがよりシンプルで明確になります。

余談ですが、パターン マッチングの最も有用な点は、良い習慣を奨励することです。最初にコーナー ケースを扱います。すべてのケースをカバーしたことは簡単に確認できます。

于 2008-10-14T03:41:19.113 に答える