Это вариант на ответ Bungus', но вот один вкладыш, который решительно уродливее, но не распространяется Binding или что-нибудь:
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
камень, вы можете отказаться от прок и явное связывание все вместе:
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}
Будьте осторожны, это медленно. В производственном коде вы, вероятно, никогда не пытаетесь это сделать, а вместо этого просто сохраняете хэш значений, поэтому программист должен поддерживать это после того, как вы не будете выследить вас и убить вас во сне.
http://stackoverflow.com/questions/6589894/access-local-variables-from-a-different-binding-in-ruby –
Я честно озадачен тем, что PHP допускает такие aberra ..., mmm, неортодоксальный код , Действительно ли 'compact' действительно принимает локальные переменные по имени и получает доступ к ним из другой функции? – tokland