The only reasonable way to backtrack multiple levels up the call stack is by throwing an exception/dying.
That said, you really should reconsider what you want to do. A programmer (including yourself, six months from now) will expect that, when a function call completes, the statement after it will execute (unless an exception is thrown). Violating that expectation will cause bugs which are caused in handle_error
, but appear to be with the code which called handle_error
, making them extremely difficult to debug. This is Not A Good Thing.
You're also making the assumption that there is absolutely no situation in which continuing after an error is handled will be appropriate. Hardcoding an assumption like that is practically a sure guarantee that, as soon as you've had time to forget it, you'll come across a case where you need to continue after calling handle_error
(and then waste huge amounts of time trying to figure out why the code after handle_error
doesn't get run).
And then there's the assumption that you'll always want to skip back exactly two levels in the call stack. That's another assumption that will fail as soon as it's hardcoded. Not only will there be cases where the calling code should continue, there will also be cases where you need to go three levels up the call stack.
So just have handle_error
exit by calling die
instead of return
and trap the exception at the appropriate level where execution should continue. You don't know every place where the sub will ever be called, so you can't predict how many levels back it will need to go.
In the code at hand, if the extra line to just say return
is bothering you, you can use return $x->handle_error;
You can even get rid of the enclosing scope and make it return $x->handle_error if $x->{size} > 1000;
There - three lines removed rather than just one, plus a pair of braces and two pairs of parentheses as a free bonus.
Finally, I would also suggest changing the name of handle_error
to better reflect what it actually does. (report_error
, maybe?) "Handling an error" usually means cleaning things up to resolve the error so that execution to continue. If you want your handle_error
to prevent the code which called it from continuing, then it seems very unlikely that it's cleaning things up to make continuation possible and, once again, it will cause nasty, hard-to-debug surprises for future programmers using this code.