MonkeeSage wrote: > On Dec 3, 10:40 pm, Charles Oliver Nutter <charles.nut... / sun.com> > wrote: > >> MonkeeSage wrote: >> >>> On Dec 3, 8:22 pm, Charles Oliver Nutter <charles.nut... / sun.com> >>> >>>> Retry outside a rescue actually allows you to jump back across call >>>> boundaries and start an invocation again. Scary. >>>> >>>> - Charlie >>>> >>> Ah. How does it unwind the stack like that? Is that what you meant >>> about implementation specific stuff? >>> >> It raises an exception, a LocalJumpError (which is how all non-local >> flow control works) which is then handled further up the stack. >> >> The reason it's implementation-specific is because the behavior ends up >> being a side effect of MRI's interpreter. >> >> The following call: >> >> foo {} >> >> Parses into an AST like this: >> >> Iter # this represents the block >> FCall :foo # this represents the call receiving the block >> nil # no args to the call >> >> Outside of a rescue, retry bubbles out to the nearest Iter. If there is >> none, it bubbles all the way out and terminates execution. The >> implementation-specific bit here is the fact that Iter contains FCall, >> rather than the more intuitive reverse; this causes the retry to go all >> the way back above the FCall and try it completely anew, reevaluating >> its receiver and arguments in the process. In compiled implementations >> or implementations with a different AST, this doesn't map well. It's >> very specific to the way MRI represents Iter/Call in the AST. >> >> >>> Ps. I don't think anyone will miss retry outside of a rescue. I won't >>> at least. :) >>> >> I've just disabled it outside of rescue in JRuby trunk; we'll see how >> that goes. So far, nothing seems breaks. >> >> - Charlie >> > > Just out of curiousity...is there a reason why MRI has Iter closing on > the FCall rather than the other way 'round? Or is it just incidental? > > Regards, > Jordan > > If Charlie did not mention this earlier in the thread we have in fact reversed that relationship in JRuby. I suspect it was reversed in MRI to make it easier to set/unset (setup/teardown) some stuff when a method call needs to pass a block. Consider: doIter { set something block related doCall unset something block related } I don't remember specifically what they set/unset but I remember this appearing to be a possible reason for it. Perhaps an MRI coder could comment since I have always wondered about this reversed relationship. -Tom -- Thomas E Enebo <thomas.enebo / sun.com> JRuby Core Developer, http://www.bloglines.com/blog/ThomasEEnebo