Re: 'next', 'last' out of subroutine
"Jonathan Swartz" <[email protected]>
| Newsgroups | gmane.comp.web.mason.devel |
|---|---|
| Message-ID | <[email protected]> |
> > [`next'|'last'] cannot be used to exit a block which returns
a
> > value such
> > as `eval {}', `sub {}' or `do {}', and should not be used to
> > exit a grep() or map() operation.
> >
> > Am I misinterpreting this statement? I do see that some modules actually
> > depend on this behavior (e.g. Test::More for its skip() subroutine).
>
> I think that maybe that statement should be rewritten as
>
> calling next|last will affect the currently "in-scope" loop. So if you
> call it in a subroutine called from a loop, it will affect that loop.
I see now, they are saying that you can't just use 'next' or 'last' to exit
a subroutine in the total absence of loops. Yes, your version would be more
clear!
> > Anyway, the way this relates to Mason is that Request::comp has always
> > relied on regaining control after its eval {} so that it can clean up
its
> > stack. But if you have a loop in one component, and a 'next' or 'last'
in
> > its child component, you can skip Mason's cleanup code entirely and end
up
> > with a corrupted stack.
>
> Why the heck would you do that?
>
> > If this is a Mason "bug", it'll be a real pain to fix - we'll have to
> > rewrite every bit of code that depends on a reliable exit from eval {}.
> > Bleah.
>
> This is not a Mason bug. People who call "next" or "last" _outside of a
> loop_ deserve what they get, or they expect what they get, and either way,
> it's not out problem.
Right. I'm not interested in trying to support this as a feature (it would
be virtually impossible), but I am concerned with the _accidental_ use of
'next' etc. If you take a large block of code from inside a loop and
refactor it into another component, you may not notice a 'next' lurking in
one of the conditional branches. We discovered that someone had done this
yesterday, and it was really hard to debug, because Mason can limp along
with a corrupted stack for a while. In our case a relative component call
finally failed because Mason had an incorrect notion of the current
component. So it's really a "bad diagnostics" type of bug.
A pretty easy "fix" would be to surround the component-calling code in
Request::comp with a useless loop:
eval {
foreach my $i (undef) {
# call $comp->run
}
}
This wouldn't warn the user about the unintended use of 'next', but it would
make 'next' act like a 'return' and not corrupt the stack. I'm assuming this
wouldn't impose a noticable performance hit.
Obviously if someone wants to do "next LABEL" or "goto", they are on their
own (but we should still dutifully document that this will mess things up).
Jon
-------------------------------------------------------
This SF.Net email is sponsored by: Oracle 10g
Get certified on the hottest thing ever to hit the market... Oracle 10g.
Take an Oracle 10g class now, and we'll give you the exam FREE.
http://ads.osdn.com/?ad_id=3149&alloc_id=8166&op=click