From: Alex Gutteridge Date: 2007-12-04T14:50:20+09:00 Subject: Re: Everyone's favorite flow control: retry On 4 Dec 2007, at 14:29, Alex Gutteridge wrote: > On 4 Dec 2007, at 00:06, Gregory Seidman wrote: > >> On Mon, Dec 03, 2007 at 02:54:32PM +0900, Charles Oliver Nutter >> wrote: >>> Today I was thinking about retry support in JRuby, and figured we've >>> reached a decision point. >> [...] >>> The problem I've run into is that it's really cumbersome to >>> implement this >>> correctly in the compiler, cumbersome enough I'm debating whether >>> we'll >>> support it. There's a few reasons for this: >>> >>> - retry is handled using exception; so every method call that >>> takes a block >>> would have to be wrapped with exception-handling for retry to work. >>> Exception-handling is expensive, even if no exceptions are >>> actually raised. >>> It would also add a significant amount of code. >>> - there's no way to know that a method will be reevaluated by >>> looking at >>> it, which makes it both dangerous and impossible to predict. >>> - nobody understands retry, and nobody uses it. >> >> Okay, I disagree with that last point. Retry is very handy when >> appropriate, and I have, indeed, used it. > > I'm pretty sure Charles meant that nobody uses or understands retry > *outside a rescue* there. Clearly it's very useful in the context of > a rescue. > >>> This also affects retry within a block >>> >>> def foo(a); puts 3; yield; end >>> >>> (print 1; self).foo((print 2; nil)) { retry } >>> >>> This also prints "123" repeatedly. > > This works for me in irb: > > irb(main):004:0> def foo(a); puts 3; yield; end > => nil > irb(main):005:0> (print 1; self).foo((print 2; nil)) { retry } > 123 > 123 > 123 > 123 > 123 > 123 > ......Ad infinitum > > But not in 1.8.6: > > [alexg@powerbook]/Users/alexg/Desktop(27): cat retry2.rb > def foo(a); puts 3; yield; end > > (print 1; self).foo((print 2; nil)) { retry } > [alexg@powerbook]/Users/alexg/Desktop(28): ruby retry2.rb > retry2.rb:3: private method `foo' called for main:Object > (NoMethodError) Sorry, I didn't cut and paste that correctly. The real output is: [alexg@powerbook]/Users/alexg/Desktop(33): ruby retry2.rb retry2.rb:3: private method `foo' called for main:Object (NoMethodError) 12[alexg@powerbook]/Users/alexg/Desktop(34): So one 'iteration' gets called, but then 'foo' somehow becomes undefined? Can anyone explain this behaviour? > Though this does: > > [alexg@powerbook]/Users/alexg/Desktop(31): cat retry.rb > class Foo > def initialize > print 1 > end > def foo(a); puts 3; yield; end > end > > Foo.new.foo((print 2; nil)) { retry } > [alexg@powerbook]/Users/alexg/Desktop(32): ruby retry.rb > 123 > 123 > 123 > 123 > 123 > ......Ad infinitum > > Color me confused, and one extra vote for removing retry outside of > rescue. > > Alex Gutteridge > > Bioinformatics Center > Kyoto University > > > Alex Gutteridge Bioinformatics Center Kyoto University