2013-07-02 71 views
6

給定一些local variables,在Ruby中compact的最簡單的方法是什麼?什麼是PHP的緊湊的Ruby等價物?

def foo 
    name = 'David' 
    age = 25 
    role = :director 
    ... 
    # How would you build this: 
    # { :name => 'David', :age => 25, :role => :director } 
    # or 
    # { 'name' => 'David', 'age' => 25, 'role' => :director } 
end 

在PHP中,我可以簡單地這樣做:

$foo = compact('name', 'age', 'role'); 
+2

http://stackoverflow.com/questions/6589894/access-local-variables-from-a-different-binding-in-ruby –

+3

我真的很困惑PHP允許這種異常...,嗯,非傳統的代碼。 'compact'真的是通過名稱獲取本地變量並從另一個函數中訪問它們嗎? – tokland

回答

9

我想出了在我原來的答覆一個顯著的改善。如果您繼承自Binding本身,則更爲乾淨。 to_sym在那裏,因爲老版本的紅寶石有local_variables作爲字符串。

實例方法

class Binding 
    def compact(*args) 
    compacted = {} 
    locals = eval("local_variables").map(&:to_sym) 
    args.each do |arg| 
     if locals.include? arg.to_sym 
     compacted[arg.to_sym] = eval(arg.to_s) 
     end 
    end 
    return compacted 
    end 
end 

使用

foo = "bar" 
bar = "foo" 
binding.compact("foo") # => {:foo=>"bar"} 
binding.compact(:bar) # => {:bar=>"foo"} 

原來的答覆

這是NEA其餘的我能得到一個行爲像PHP的compact的方法 -

方法

def compact(*args, &prok) 
    compacted = {} 
    args.each do |arg| 
    if prok.binding.send(:eval, "local_variables").include? arg 
     compacted[arg.to_sym] = prok.binding.send(:eval, arg) 
    end 
    end 
    return compacted 
end 

例如使用

foo = "bar" 
compact("foo"){} 
# or 
compact("foo", &proc{}) 

它不是完美的,但因爲你必須通過一個PROC英寸我接受關於如何改善這一點的建議。

+1

看來你可以在循環之外放置'eval',不是嗎? –

+0

@SergioTulentsev謝謝你。 – Bungus

1

這是Bungus'回答一個變種,但這裏有一個一行是斷然醜陋,但不延長綁定或任何東西:

foo = :bar 
baz = :bin 
hash = [:foo, :baz].inject({}) {|h, v| h[v] = eval(v.to_s); h } 
# hash => {:baz=>:bin, :foo=>:bar} 

您也可以使它看起來勝負的樣濫用塊結合的方法調用 - 再次,在Bungus'原來的答覆變體:(我就告訴自己,{[..]}是垃圾壓實符號)

module Kernel 
    def compact(&block) 
    args = block.call.map &:to_sym 
    lvars = block.binding.send(:eval, "local_variables").map &:to_sym 
    (args & lvars).inject({}) do |h, v| 
     h[v] = block.binding.send(:eval, v.to_s); h 
    end 
    end 
end 

foo = :bar 
baz = :bin 
compact {[ :foo, :bar, :baz ]} 
# {:foo=>:bar, :baz=>:bin} 

如果使用binding_of_caller寶石,你可以放棄PROC 顯式綁定一起:

require 'binding_of_caller' 
module Kernel 
    def compact(*args) 
    lvars = binding.of_caller(1).send(:eval, "local_variables").map &:to_sym 
    (args.map(&:to_sym) & lvars).inject({}) do |h, v| 
     h[v] = binding.of_caller(2).send(:eval, v.to_s); h 
    end 
    end 
end 

foo = :bar 
baz = :bin 
compact :foo, :bar, :baz 
# {:foo=>:bar, :baz=>:bin} 

被警告,它的速度慢。在生產代碼中,你應該永遠不要試圖去做這件事,而應該保留一個值的散列值,這樣程序員在你之後不得不維持這個值,並不會在你的睡眠中追捕你並殺死你。

相關問題