2012-01-20 121 views
2

我正在使用耙子任务来接收和处理数据。红宝石散列与方法对

数据看起来像"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]) 

红宝石不喜欢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中使用了类似的实现:)无论哪种方式,发送方法工作得很好。 – dcarneiro

+0

在JavaScript中,'taskA'是一个方法引用,'taskA()'是一个方法调用。在Ruby中,由于括号是可选的,因此'taskA'和'taskA()'都是方法调用。你可以使用'taskA_proc = method(:taskA)'捕获一个Proc,然后用'taskA_proc.call()'调用它,但是这通常比使用'send'更笨拙。 – tadman

2

定义“不喜欢”。

如果您尝试使用功能名称来初始化哈希:在函数定义

  1. 之前,你会得到一个未定义的符号。
  2. 函数定义后,您只是执行该函数。

如果要映射值的功能,你可以打电话,考虑定义的方法作为特效/ lambda表达式:

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

你可以存储符号,太多,但我更喜欢使用已知现存文物,就像一个变量,所以IDE可以帮助我确保我做的事情是正确的,因为它可以知道–符号是任意的,并且没有办法确保它们与除调用它之外的现有方法对齐。

+0

这工作得很好,并感谢红宝石如何与功能工作。但我最终会去@tadman解决方案beucase它似乎更干净。无论哪种方式+1工作的答案 – dcarneiro

+0

@丹尼尔IMO它实际上不太干净,因为错误的机会增加,但单元测试可以帮助消除这种情况。海事组织的方法应该真的是一个具有已知接口的类; *这是最干净的 - IDE协助,封装,并且不需要在周围放置符号。 –