Мне нужно, чтобы блоки определялись и вызывались в пределах класса, используя instance_exec
(через Rails 2.3.2). Однако некоторые из этих блоков должны возвращаться рано в некоторых ситуациях, что вызывает у меня проблему.
Мое приложение было построено с использованием ruby 1.8.6, но мне нужно запустить его и на 1.8.7. Кажется, что между двумя версиями была удалена возможность возврата изнутри лямбды. Следующее работает в 1.8.6, но выдает LocalJumpError
(неожиданный возврат) в 1.8.7:
class Foo
def square(n)
n ** 2
end
def cube(n)
n ** 3
end
def call_block(*args, &block)
instance_exec *args, &block
end
end
block = lambda { |n|
return square(n) if n < 5
cube(n)
}
f = Foo.new
f.call_block(5, &block) # returns 125
f.call_block(3, &block) # returns 9 in 1.8.6, throws a LocalJumpError in 1.8.7
Я решил, что смогу заставить его работать в 1.8.7, если заменит return
в своем блоке на next
, но next square(n) if n < 5
приведет к nil
в 1.8.6.
Есть ли способ заставить это работать как в 1.8.6, так и в 1.8.7? Я знаю, что могу реструктурировать свои блоки для использования ветвления вместо раннего возврата, но некоторые блоки являются более сложными и имеют несколько ситуаций, когда требуется ранний возврат.
Кроме того, это изменится, если я хочу, чтобы мой код работал в ruby 1.9?
Редактировать: Я обнаружил, что причина, по которой он работает в 1.8.6, а не в 1.8.7, в том, что 1.8.7 определяет свой собственный instance_exec
в источнике C, тогда как 1.8.6 использует Реализация рельсов. Если я переопределю instance_exec
в 1.8.7 с версией Rails, он тоже будет работать.