Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Continuations in Perl - Returning to an arbitrary level up the call stack

by unlinker (Monk)
on May 18, 2013 at 20:22 UTC ( #1034144=perlquestion: print w/ replies, xml ) Need Help??
unlinker has asked for the wisdom of the Perl Monks concerning the following question:

Greetings Venerable Monks,

I have a need to return from a deeply nested function, not to the caller, but to a higher point up the call stack. After grovelling at the feet of Google, I understand that, what I need are "Continuations" - functions that not only specify what to return, but also specify where to return to, up the call stack.

The only way I can think of doing this is by throwing exceptions (say at nesting level 4) and catching them at a specified position up the call chain (say at nesting level 1). But it somehow seems wrong (what if a function between 1 and 4 catches it? What if some other legitimate exceptions are thrown?).

Can I implement continuations in Perl in a more disciplined/organized fashion? If yes, can the wise monks here educate me with an example please?

Comment on Continuations in Perl - Returning to an arbitrary level up the call stack
Re: Continuations in Perl - Returning to an arbitrary level up the call stack
by vsespb (Hermit) on May 18, 2013 at 20:28 UTC
    some links http://en.wikipedia.org/wiki/Continuation http://search.cpan.org/perldoc?Coro
Re: Continuations in Perl - Returning to an arbitrary level up the call stack (goto)
by LanX (Canon) on May 18, 2013 at 20:38 UTC
    doesnt sound like you need continuations, I think a simple goto is enough, just put a label at the target position.

    update

    my $i=0; target(); sub target { rec(); TARGET: print "END"; } sub rec { $i++; print "IN $i\n"; goto TARGET if ($i>5); # return skipping multiple levels rec(); # 6 levels recursive call print "OUT $i\n"; # never reached }
    out...
    IN 1 IN 2 IN 3 IN 4 IN 5 IN 6 END

    Cheers Rolf

    ( addicted to the Perl Programming Language)

    update

    added comments

      Unfortunately, the functions up the call stack are modules that I dont control. These modules call my function and I dont want to return to the calling module but one level higher up the stack.

      Thanks for the suggestion though. I am currently looking at Continuation::Escape for a possible solution

        > I dont want to return to the calling module but one level higher up the stack.

        Thats where you have to place the target label.

        Anyway I doubt that your approach is reasonable, sorry! Maybe a XY problem?

        Cheers Rolf

        ( addicted to the Perl Programming Language)

Re: Continuations in Perl - Returning to an arbitrary level up the call stack
by Anonymous Monk on May 18, 2013 at 20:49 UTC
    One option to think about is to refactor the function(s) to reduce the nesting.
Re: Continuations in Perl - Returning to an arbitrary level up the call stack
by tobyink (Abbot) on May 18, 2013 at 20:54 UTC

    There's Scope::Upper which provides unwind_at that essentially allows you to perform a return higher up the stack.

    You could also try Return::MultiLevel which seems to provide a pretty sane interface for continuations, albeit requiring some co-operation between caller and callee. Also take a look at some of MAUKE's other modules that follow on from that.

    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
      Thanks! Return::MultiLevel is exactly what I was looking for.
        > Thanks! Return::MultiLevel is exactly what I was looking for.

        Of course, it uses goto under the hood, just hidden behind massive abstraction and overhead ... 8-|

        Cheers Rolf

        ( addicted to the Perl Programming Language)

        ) Unfortunately there is no emoticon for shaking the head and sighing...

Re: Continuations in Perl - Returning to an arbitrary level up the call stack
by BrowserUk (Pope) on May 18, 2013 at 23:09 UTC
    I have a need to return from a deeply nested function, not to the caller, but to a higher point up the call stack.

    Every time I've found my code needing something as crazy as that, I've thrown the code away, got drunk/sober/laid/slept, whatever it took me to forget the idea and then come back and started over.

    What you are suggesting sound likes bypassing the stairs by jumping from one landing to the next; and whilst Parkour makes for some great movie chases and youtube clips; designing a building that relied on it for emergency exits just isn't on.

    But that exactly what you are doing by designing your code to rely upon such shortcuts.

    I bet if you were to describe your application in sufficient detail that you'd get a raft of better solutions that don't require the equivalent of leaping from one tall building to the next as part of your daily commute.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      I agree in general, but there are some good use cases.

      For instance, when designing a recursion to search a graph it's sometimes desirable to stop immediately after the goal is reached.

      No need to backtrack and branch thru the whole labyrinth after the exit is already found!

      And the recursion is much simpler w/o special case handling for chained returns.

      Perl internally cares about cleaning up all intermediate frames.

      Cheers Rolf

      ( addicted to the Perl Programming Language)

        For instance, when design a recursion to search a graph it's sometimes desirable to stop immediately after the goal is reached.

        I'm having trouble imagining a routine designed to search a graph, where finding the target is a special case?

        No need to backtrack and branch thru the whole labyrinth after the exit is already found!

        The emotive language makes it sound like returning from (several nested) subroutines is a difficult thing to do; but that is what subroutines do. Via a return or falling off the end. it is neither hard to program nor costly in executions time.

        Indeed, whatever alternative mechanism is used, in whatever language, it will always be more costly than the natural return chain. The stack still has to be unwound

        Just as the exception mechanism in C++ (or structured exceptions in MSC), are a magnitude or more expensive because they have to search back up the stack looking for stack frames interpreting them as they go; so the goto that underlies such mechanisms in Perl has to go through an equally convoluted process to find a label at the appropriate scope.

        Such costs and overheads -- not to mention the difficulties they create when they fail to work as expected and need to be traced and debugged -- are just about acceptable for the exceptional (rare, non-normal) cases they are designed for; but wrapping them over in a cute sounding abstraction and subverting them for use in the general case -- such as a search routine finding what it is looking for -- seems like abuse of the very worse kind to me.

        Whilst I'm sure it is possible to contrive a theoretical use case that might stand up to cursory inspection; but unless I saw a real-world use case that I couldn't find a less obscure alternative, any use of the mechanism would garner a big red flag in any code review I was involved in.

        Luckily, neither the OP nor you have to subject your code to my review :)


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        You are reinventing exception handling.

        While a daily routine for a Python programmer most Perl hackers won't understand it.

        Don't bother preaching, switch to Python! :-D

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1034144]
Approved by Perlbotics
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (15)
As of 2014-07-30 09:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (230 votes), past polls