2011-08-11 39 views
4

我無法弄清楚如何將函數調用分配給紅寶石散列。 我想要做的是將函數分配給散列鍵,然後 使用經典散列查找語法調用此函數。Ruby:如何將函數映射到散列

def Foo() 
    puts "bar" 
end 

puts "Assigning" 
test = { "foo" => Foo() } 

puts "Executing" 
test["foo"] 

此代碼失敗,函數foo是puts "Assign"後調用,哈希在創建過程中和之後puts "Executing"

def Foo() 
    puts "bar" 
end 

puts "Assigning" 
test = { "foo" => Foo } 

puts "Executing" 
test["foo"] 

與此代碼我收到uninitialized constant Foo (NameError)什麼也沒有發生。

最後用

def Foo() 
    puts "bar" 
end 

puts "Assigning" 
test = { "foo" => :Foo } 

puts "Executing" 
test["foo"] 

我得到不輸出。

有什麼建議嗎?

感謝大家的回答和建議。

我現在要做的是測試 如果基於哈希方法調用函數比 基於if/case語句的等效代碼更快。

funcs["foo"].call

fatser比

if func_name == "foo" then 
    Foo() 
elsif ... 
... 
end 

case func_name 
when "foo" 
    Foo() 
when ... 
    ... 
end 

顯然,對於一個大的數目的函數(〜150)和數百 主叫週期

+0

一個快速的建議 - 沒有定義功能與標題案例; Ruby會期望它是一個常量而不是一個函數。 – Simon

回答

3

沒有容易的可能性使你的福nction通過檢索withput重寫Hash[]方法中,作爲弗拉德指出散列鍵簡單地執行,即

def foo 
    puts "hi" 
end 

... # magic 

test["foo"] # outputs hi 

將不起作用。你能做什麼,雖然是使用Object#method分配方法的參考,然後用call調用它:第一

def foo 
    puts "hi" 
end 

test = { "foo" => method(:foo) } 

test["foo"].call # => hi 
0

第一件事,用小寫字母開頭的方法名。然後,轉到第一個示例,Ruby很渴望​​Foo被調用。

在第二個例子中,以大寫字母開頭的變量被認爲是常量,所以Ruby會尋找一個,而不會去尋找一個方法。考慮到如果foo其中一個方法然後foo將被調用,如第一個例子。

第三個例子:test["foo"]返回:Foo,一個符號。代碼Foo()中沒有任何地方被調用。

* 建議

1。 - 看看Ruby中的標識符命名法。

2:你可以在lambdaProcObject#method

3.-接過來一看如果你有閒錢,不介意買了一雙書,給在Ruby編程Ruby和元編程機會(既可以在PragProg購買。

0

你可以嘗試使用哈希構造與塊,所以

def foo 
    puts "hi" 
end 

test = Hash.new do |hash, key| 
    send(key) if respond_to?(key) 
end 

test["foo"] # prints "hi", returns nil 
4

你可以使用拉姆達的替代方法。兩種常用選項H ERE:

hash = {:foo => lambda { puts 'bar } } 

hash[:foo].call 

第二(更復雜)是這樣的:

irb(main):001:0> class Hash 
irb(main):002:1> alias :orig_anc :'[]' 
irb(main):003:1> 
irb(main):004:1* def [](key) 
irb(main):005:2>  if orig_anc(key).is_a? Proc 
irb(main):006:3>  orig_anc(key).call 
irb(main):007:3>  else 
irb(main):008:3*  orig_anc(key) 
irb(main):009:3>  end 
irb(main):010:2> end 
irb(main):011:1> end 
=> nil 
irb(main):012:0> h = {:hello => 'world', :foo => lambda { puts 'bar' }} 
=> {:hello=>"world", :foo=>#<Proc:[email protected](irb):12 (lambda)>} 
irb(main):013:0> h[:hello] 
=> "world" 
irb(main):014:0> h[:foo] 
bar 
=> nil 
irb(main):015:0> 

第二個只允許您使用跳過「呼」的方法