"retry" without "rescue" seems pointless to me. As far as I can see "retry"'s main purpose is repetition in case of exceptions. The use that you demonstrate looks like a untypical and probably unwanted idiom which accidentally happened to work in 1.8.* to me.
Apparently the _syntax_ was changed to allow "retry" only in "rescue" clauses - which makes perfectly sense for me. I am not the definitive source but to me it looks like 1.9 fixes a misbehavior of 1.8 - if that's the case I would not want to reintroduce this just to make 1.9 more compatible to 1.8. In fact, 1.9 purposefully *does* have some incompatibilities.
That mimics the example (where the retry is unconditional), but
clearly isn't a general solution; If "redo" works on 1.9 (which is
similar to retry, but different in conditions not relevant to the
question), that may be the answer.
···
On Sun, Apr 19, 2009 at 9:50 AM, James Gray <james@grayproductions.net> wrote:
On Apr 19, 2009, at 9:20 AM, Yoann Guillot wrote:
It seems that the 'retry' keyword is not supported anymore in ruby1.9 to
restart a running iteration from the beginning.
As Robert said, it's no longer supported in iteration. It still works in a
rescue clause.
Is there a way to achieve the old behavior, preferably in a 1.8 compatible
way ?
I'll be surprised if more complex examples can't be similarly converted fairly easily. That was kind of my point. I meant the code to say, take a step back and think what is this trying to do…
James Edward Gray II
···
On Apr 19, 2009, at 12:01 PM, Christopher Dicely wrote:
On Sun, Apr 19, 2009 at 9:50 AM, James Gray > <james@grayproductions.net> wrote:
On Apr 19, 2009, at 9:20 AM, Yoann Guillot wrote:
Is there a way to achieve the old behavior, preferably in a 1.8 compatible
way ?
My code walks an array, and may change the current element, which is allowed
without breaking the iteration.
I have also a special case where i have to change a whole subsection of the
array, this was the case where i used 'retry'
eg
ary.each { |e|
case e
when foo
ary[ary.index(e)] = foo(e)
when bar
when ...
when baz
ary[ary.index(e), 12] = [flublu]
retry
end
}
Sure, i could use map or many other ways, my code is quite ugly anyway.
I was just surprised by the change of behavior.
I don't see the point in removing capabilities from the language (restarting
an iteration from within), but I can sure live with it.
···
On Mon, Apr 20, 2009 at 02:10:33AM +0900, James Gray wrote:
On Apr 19, 2009, at 12:01 PM, Christopher Dicely wrote:
That mimics the example (where the retry is unconditional), but
clearly isn't a general solution;
I'll be surprised if more complex examples can't be similarly converted
fairly easily. That was kind of my point. I meant the code to say, take
a step back and think what is this trying to do?
My code walks an array, and may change the current element, which is allowed without breaking the iteration.
I have also a special case where i have to change a whole subsection of the array, this was the case where i used 'retry'
eg
ary.each { |e|
case e
when foo
ary[ary.index(e)] = foo(e)
when bar
when ...
when baz
ary[ary.index(e), 12] = [flublu]
retry
end
}
Sure, i could use map or many other ways, my code is quite ugly anyway.
Yeah, for a case like this, I would probably just resort to tracking an index in a variable and using a boring while loop. 90% of the time it's wrong to track your own index in Ruby, but I think you're squarely in the special 10% here.
Really, you should already be using each_with_index() above because your repeated calls to index() are inefficient for big data sets (rewalking possibly large portions of the Array) and they break if the data set contains duplicate entries.
Plus, I'm just not comfortable relying on the iterators to do the right thing while I edit the collection out from underneath them. Obviously it was working for you, but I'm not confident enough to trust it under all cases.
I don't see the point in removing capabilities from the language (restarting an iteration from within), but I can sure live with it.
It was done because retry had some nasty side effects and was causing performance issues:
begin
ary.each { |e|
case e
when :foo
ary[ary.index(e)] = foo(e)
when :bom
ary[ary.index(e)] = :foobom # to show retry
when :baz
ary[ary.index(e), 12] = [:flublu]
raise Retry
end
}
rescue Retry
retry
end
p ary
__END__
[:foobom, :bar, :flublu]
but as you point out, this is not restarting the iteration from within.
Regards,
Sean
···
On Sun, Apr 19, 2009 at 7:17 PM, Yoann Guillot <john-rubytalk@ofjj.net> wrote:
On Mon, Apr 20, 2009 at 02:10:33AM +0900, James Gray wrote:
On Apr 19, 2009, at 12:01 PM, Christopher Dicely wrote:
That mimics the example (where the retry is unconditional), but
clearly isn't a general solution;
I'll be surprised if more complex examples can't be similarly converted
fairly easily. That was kind of my point. I meant the code to say, take
a step back and think what is this trying to do?
My code walks an array, and may change the current element, which is allowed
without breaking the iteration.
I have also a special case where i have to change a whole subsection of the
array, this was the case where i used 'retry'
eg
ary.each { |e|
case e
when foo
ary[ary.index(e)] = foo(e)
when bar
when ...
when baz
ary[ary.index(e), 12] = [flublu]
retry
end
}
Sure, i could use map or many other ways, my code is quite ugly anyway.
I was just surprised by the change of behavior.
I don't see the point in removing capabilities from the language (restarting
an iteration from within), but I can sure live with it.
Or using throw/catch. You can also factor out the pattern, for example:
def retryable
loop do
catch(:retry) do
yield
return
end
end
end
ary = [:foo, :bar, :baz, :foo]
def foo(e)
:bom
end
retryable do
ary.each { |e|
case e
when :foo
ary[ary.index(e)] = foo(e)
when :bom
ary[ary.index(e)] = :foobom # to show retry
when :baz
ary[ary.index(e), 12] = [:flublu]
throw :retry
end
}
end
p ary
__END__
[:foobom, :bar, :flublu]