in reply to Re^9: Continuations in Perl - Returning to an arbitrary level up the call stack
in thread Continuations in Perl - Returning to an arbitrary level up the call stack

Well this is far beyond what the OP wanted!
Why do you think so? he mention call stack:
but to a higher point up the call stack.
Your code is a bit cheat - you implemented another subroutine, just to remember point in the stack. In my code, during executiom, there was just one "longjump" always to same point, so you had to implement just one subroutine with one label. But in general case you need N goto lables (N is unknown at compilation stage), so it's impossible without eval EXPR (not eval BLOCK)
Try this,
use strict; use warnings; use Return::MultiLevel qw/with_return/; our %returns; sub rec { my ($i) = @_; $i++; print ">> i=$i\n"; if ($i <= 9) { with_return { $returns{$i} = shift; rec($i); }; } if (@ARGV) { my $r = shift @ARGV; print "RESTORE $r\n"; $returns{$r}->(); } print "<< i=$i\n"; } rec(0); __END__
$perl ml_a.pl 6 >> i=2 >> i=3 >> i=4 >> i=5 >> i=6 >> i=7 >> i=8 >> i=9 >> i=10 RESTORE 6 << i=6 << i=5 << i=4 << i=3 << i=2 << i=1
$perl ml_a.pl 3 >> i=1 >> i=2 >> i=3 >> i=4 >> i=5 >> i=6 >> i=7 >> i=8 >> i=9 >> i=10 RESTORE 3 << i=3 << i=2 << i=1

And let's consider @ARGV as external input, which is available only just before program go to 'RESTORE' point, but not before program started a recursion

Replies are listed 'Best First'.
Re^11: Continuations in Perl - Returning to an arbitrary level up the call stack
by LanX (Saint) on May 19, 2013 at 12:44 UTC
    This is getting more and more abstract and convoluted! Dynamic jump-levels? Come on...

    I'm hacking for 30 years now and never needed this! :)

    In this concrete case I would only call target() if a recursion level is really expected to be a jump target, that are 6 and 3 in your examples.

    (If not possible in advance I would just step back single levels (return or goto) till I reach the desired one, Something like eval "LABEL:" would be my very last resort)

    And even multiple calls to target are no problem, cause the goto always jumps to the last TARGET -label in the call-stack and local $target cares about restoring previous levels. This works w/o any string- eval.

    I would never use with_return in the way you are showing, because

    1. it's not obvious what it does, I can name the target() function in a expressive way

    2. it has plenty of overhead, many of my recursions are long-running branch-and-bound searches which need to be optimized.

    3. the need to explicitly pass the return-sub along is IMHO very annoying

    > Your code is a bit cheat - you implemented another subroutine, just to remember point in the stack.

    Nope, it's like in the original code I gave. And as I said Return::MultiLevel just uses the same technique under the hood.

    Anyway let's stop it here please! =)

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      > This is getting more and more abstract and convoluted! Dynamic jump-levels? Come on...

      I'm bored ... voila!

      use strict; use warnings; our $restore; sub rec { my ($i) = @_; $i++; print ">> i=$i\n"; if ($i <= 9) { target($i); } goto TARGET if $i > $restore; print "<< i=$i\n"; } sub target{ rec(shift); TARGET: } #--- Tests for $restore (6,3){ print "\n\n","-"x5," Restore at $restore\n"; rec(0); } __END__ ----- Restore at 6 >> i=1 >> i=2 >> i=3 >> i=4 >> i=5 >> i=6 >> i=7 >> i=8 >> i=9 >> i=10 << i=6 << i=5 << i=4 << i=3 << i=2 << i=1 ----- Restore at 3 >> i=1 >> i=2 >> i=3 >> i=4 >> i=5 >> i=6 >> i=7 >> i=8 >> i=9 >> i=10 << i=3 << i=2 << i=1

      Again less and clearer code, and w/o generating dynamic labels with eval!

      Cheers Rolf

      ( addicted to the Perl Programming Language)

        And this is cheat again. 'goto' executed 4 times in 1st test, and 7 times in last test. You can achieve same if replace 'goto' with return, there won't be 'goto' in this code at all then (i.e. you rewrited this one particular case with plain recursion, without jumping frames)

        And by the way, just in case if you pretend that it's always best to work that way, here is your posting where you explain to another monk, that it's not http://www.perlmonks.org/?node_id=1034169

        For instance, when designing a recursion to search a graph it's sometimes desirable to stop immediately after the goal is reached.
        Also, this your cite explains everything
        goto always jumps to the last TARGET -label in the call-stack and
        So,

        1 LABEL in source code can "remember" 1 stackframe.

        and

        1 with_return statement in source code can "remember" N stackframes.

      Anyway let's stop it here please! =)
      Ok, but just to summarize this subthread:
      Return::MultiLevel functionality cannot be re-invented with goto, and all your listed arguments against this are not valid, emotional, or not directly related to the case =)
        > Return::MultiLevel functionality cannot be re-invented with goto,

        Which is still nonsense since the module is based on goto LABEL.

        > and all your listed arguments against this are not valid, emotional, or not directly related to the case =)

        Well this attitude pretty much summarizes the impression I already got from you ...

        Please, go on down-voting me!

        Cheers Rolf

        ( addicted to the Perl Programming Language)