2012-01-20 6 views
2

私はデータを受け取り、処理するためにレーキタスクを使用しています。ペアのメソッドを含むrubyハッシュ

データは"code:value"のように見え、各コードは特定の動作にマッピングされています。

たとえば、"0xFE:0x47"は、0x47というパラメータを持つ0xFEタグに対応するメソッドを呼び出します。

tags = Hash[0xFA => taskA, 0xFB => taskB, 0xFC => taskC] 

def taskA(value) 
    ... 
end 

def taskB(value) 
    ... 
end 

def taskC(value) 
    ... 
end 

、その後、メッセージを受信したとき、splitを行うと、ハッシュにメソッドを呼び出し、同様に:私は、これはハッシュにマッピングする必要がありますし、方法は以下に定義されていると思うスケーラビリティの目的のために

tokens = message.split(':') 
tags[tokens[0]](tokens[1]) 

RubyではHashの初期化が嫌いです。この問題を解決する正しい方法は何ですか?

答えて

2

JavaScriptで動作しているように、メソッドが呼び出されるまで単なる参照であることを期待しているかもしれませんが、そうではありません。最善のアプローチは、シンボルとしてそれらを維持し、それらを呼び出すためにsend方法を使用することである。

# Define a mapping table between token and method to call 
tags = { 
    0xFA => :taskA, 
    0xFB => :taskB, 
    0xFC => :taskC 
} 

tokens = message.split(/:/) 

# Call the method and pass through the value 
send(tags[tokens[0]], tokens[1]) 

Hash[]初期化は、通常、ハッシュに配列を変換するときなどの特殊なケースのために予約されています。この場合、混乱しないように冗長であるため、最善の方法は省略されています。 { ... }には、暗黙的にハッシュを作成する効果があります。

+0

私は既にJavaScriptで同様の実装を使用しています:)どちらの方法でも、sendメソッドはうまくいきました。 – dcarneiro

+0

JavaScriptでは、 'taskA'はメソッド参照であり、' taskA() 'はメソッド呼び出しです。 Rubyでは、大括弧はオプションであるため、 'taskA'と' taskA() 'はどちらもメソッド呼び出しです。 'taskA_proc = method(:taskA)'を使ってProcを捕捉し、 'taskA_proc.call()'で後で呼び出すことができますが、これは 'send'を使うよりも通常は面倒です。 – tadman

2

「好きではない」と定義します。

あなたは関数名を使用してハッシュを初期化しようとする場合は、次の関数が定義されている

  1. する前に、あなたは未定義のシンボルを取得します。
  2. 関数が定義されたら、関数を実行するだけです。

    > taskA = lambda { |value| puts "foo #{value}" } 
    > h = { 0x42 => taskA } 
    > h[0x42].call("bar") 
    foo bar 
    

    あなたも、シンボルを格納することができますが、私は知ら-既存の成果物を使用することを好む:

  3. あなたは、あなたが呼び出すことができる関数に値をマッピング手続きオブジェクト/ラムダとしてメソッドを定義することを検討したい場合

変数のように、IDEは–シンボルが任意であり、呼び出すこと以外の既存のメソッドと揃うようにする方法がないので、私が正しいことを実行できることを確認するのに役立ちます。

+0

これはうまく動作し、ルビがどのように関数で動作するかを頭にお礼します。しかし、私はそれがよりクリーンなように見える@タッドマンソリューションbeucaseを終了します。いずれかの方法+1の作業の答え – dcarneiro

+0

@ダニエルIMOそれは実際にはエラーの可能性が増えてきれいではありませんが、単体テストはそれを排除するのに役立ちます。 IMOは実際には既知のインターフェースを持つクラスでなければなりません。 *それは*最もクリーンです - IDEの支援、カプセル化、シンボルを投げる必要はありません。 –