6

ゲームサーバーにHaskellを使おうと思ったのですが、コーディングの際にパケットを解析する部分を見て「うわぁ、パターンマッチングが多くなるな」と思ってしまいました。これを見ると、行われるマッチの量が多くなります (そこを歩く、攻撃する、略奪する、開くなど)。

私がすることは:

  1. パケットを受信する
  2. パケット ヘッダーを 16 進数の文字列に解析します (たとえば、「02B5」とします)。
  3. パケットから残りのデータを取得する
  4. parseIO の一致ヘッダー
  5. パケットの内容で適切な関数を呼び出す

String -> method をマッピングするのは簡単ですが、メソッドには異なる量の in-parameters があります。

以下に示す単純な 2 つのパターン マッチングの方法を考えました。

#1
packetIO :: String -> IO ()
packetIO packet =
  case packet of
    "02B5" -> function1
    "ADD5" -> function2
    ... and so on

#2
packetIO :: String -> IO ()
packetIO "02B5" = function1
packetIO "ADD5" = function2
... and so on

パフォーマンスとコーディング スタイルの両方を見て、クライアントから受信したパケットをより適切に処理する方法はありますか?

見つけられなかったリソースやリンクがある場合は、その方向を教えてください。

編集130521

以下にリストされている両方の選択肢が良い選択であるようです。コメントで私の質問への回答を待ってから、どれが私にとって最良の解決策であるかを選択してください.

  1. (ByteString -> Function) を Map 構造体に格納します。O(ログ n)
  2. ByteString を Word16 に変換し、パターン マッチを行います。ツリーを介した O(log n) またはルックアップ テーブルを介した O(1)

編集130521

Philip JF が言ったように、Word16 でパターン マッチングを行うことにしました。どちらも優れた代替手段であり、私の推測ではどちらも同じように高速ですが、Word16 に変換する必要がないことを考えると、Map の方が高速である可能性があります。

packetIO 0x02B5 = function1
packetIO 0xADD5 = function2
etc
4

2 に答える 2

10

どちらの機能も同等です。コンパイラは、2 番目のものを最初のものに脱糖します。パターン マッチングは、 のシンタックス シュガーですcase

caseはこんなことに最適です。O(1)であるジャンプテーブルにコンパイルされます。つまり、リストしたソリューションの両方が最適であることを意味します。

コーディング スタイルに関する限り、どちらのスタイルも完全に慣用的です。個人的にcaseはパターン マッチングよりも好きですが、他の多くの人がトップレベル関数のパターン マッチングを好むことも知っています。

于 2013-05-21T00:18:22.357 に答える