Прежде всего, block.call()
выполняется с yield
, и вам не нужен параметр &block
.
Обычно вы не можете делать то, что хотите, блоки связаны при их создании, а внутри блока вы можете видеть локальные переменные, определенные в этот момент; Самый простой способ сделать то, что вы хотите, а не то, как вы будете обычно использовать блоки, это:
def test()
foo = yield if block_given?
puts "in test, foo is #{foo}"
end
test() {
foo="this is foo"
}
Но это только побочный эффект, потому что foo
"возвращается" блоком. Если вы вместо этого сделаете это:
def test()
foo = yield if block_given?
puts "in test, foo is #{foo}"
end
test() {
foo="this is foo"
"ha ha, no foo for you"
}
Вы заметите, что он делает что-то другое.
Вот еще волшебство:
def test(&block)
foo = eval "foo", block.binding
puts foo
block.call
foo = eval "foo", block.binding
puts foo
end
foo = "before test"
test() {
foo = "after test"
"ha ha, no foo for you"
}
Это бы сработало, но оно сломается, если вы удалите foo = "before test"
, потому что foo
становится локальной переменной в блоке и не существует в привязке.
Сводка: вы не можете получить доступ к локальным переменным из блока, только к локальным объектам, в которых был определен блок, и возвращаемому значению блока.
Даже это не сработает:
def test(&block)
eval "foo = 'go fish'", block.binding
block.call
bar = eval "foo", block.binding
puts bar
end
потому что foo
в привязке отличается от локального в блоке (я этого не знал, спасибо).