in reply to Re^8: 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

> Here is example.

Well this is far beyond what the OP wanted!

And your $return->() if $return clause makes it quite esoteric ...

> Try do same with "goto"

... FWIW!

use strict; use warnings; our $target=""; sub rec { my ($i) = @_; $i++; print "i=$i $target\n"; if ($i == 3) { target($i); } if ($i == 5) { goto $target if $target; } if ($i == 7) { return; } rec($i); } sub target { local $target="TARGET"; rec(shift); TARGET: } rec(0); __END__ i=1 i=2 i=3 i=4 TARGET i=5 TARGET i=4 i=5 i=6 i=7

As I said it's only an abstraction of the goto mechanism!

Good night! =)

Cheers Rolf

( addicted to the Perl Programming Language)

Replies are listed 'Best First'.
Re^10: Continuations in Perl - Returning to an arbitrary level up the call stack
by vsespb (Chaplain) on May 19, 2013 at 09:56 UTC
    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

      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)

        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 =)