Можно ли получить доступ к области блока в методе? - PullRequest
2 голосов
/ 12 февраля 2012

Я хотел бы написать метод (define_variables), который может получить block и использовать переменные, определенные в нем.Является ли это возможным?Например, я хотел бы получить 5 в выводе:

module A
  def self.define_variables
    yield
    puts a # not 5 :(
  end
end

A::define_variables do
  a = 5
end

Возможно, есть некоторые трюки с eval, но пока никого не нашли.

Ответы [ 2 ]

5 голосов
/ 12 февраля 2012

Короче, нет. После того, как вы вызвали yield, эти переменные, определенные в блоке, ушли (вроде, как мы увидим), за исключением того, что возвращается - именно так работает объем. В вашем примере, 5 все еще существует в том смысле, что оно возвращается блоком, и, таким образом, puts yield будет печатать 5. Используя это, вы можете вернуть хеш из блока {:a => 5}, а затем получить доступ к нескольким «переменным» таким образом. В Ruby 1.8 (в IRb только ) вы можете сделать:

eval "a = 5"
a # => 5

Хотя я в любом случае не знаю eval содержимого блока. Несмотря на это, в Ruby 1.9 область действия eval была изолирована , и это даст вам NameError. Вы можете сделать eval в контексте Binding, хотя:

def foo
  b = yield
  eval(a, b) + 2
end

foo do
  a = 5
  binding
end # => 7

Мне кажется, что вы пытаетесь эмулировать макросы в Ruby, что просто невозможно (, по крайней мере, не чистый Ruby ), и я не рекомендую использовать любой из " Обходные пути "Я упоминал выше.

2 голосов
/ 12 февраля 2012

Согласился, что это немного задом наперед, и объяснение Эндрю верно.Если ваш вариант использования определяет переменные, однако, уже есть методы class_variable_set и instance_variable_set, которые отлично подходят для этого:

module A
  def self.define_variables(vars = {})
    vars.each { |n, v| class_variable_set n, v }
    puts @@a
  end
end

A::define_variables :@@a => 5

Выше приведен пример того, как это будет работатькод, который вы опубликовали, а не рекомендацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...