Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Re^4: Can I check if a loop's scope is entered for the first time? (Devel::Callsite)

by TheDamian (Vicar)
on May 07, 2018 at 05:03 UTC ( [id://1214136]=note: print w/replies, xml ) Need Help??


in reply to Re^3: Can I check if a loop's scope is entered for the first time? (Devel::Callsite)
in thread Can I check if a loop's scope is entered for the first time?

Well, that took longer than I expected. ;-)

I just uploaded a new release of Var::Pairs (version 0.003005)
that solves the problem of resetting an iterator on premature termination
of the surrounding loop. It does so by using Scope::Upper::reap()
to install a "destructor" for each iterator when execution leaves
the surrounding scope.

Take another look; I think it's likely this technique would also work for you.

Damian

Replies are listed 'Best First'.
Re^5: Can I check if a loop's scope is entered for the first time? (Devel::Callsite)
by TheDamian (Vicar) on May 07, 2018 at 06:09 UTC
    I think it's likely this technique would also work for you.

    In fact, more than just likely...

    sub from (&$) { use Devel::Callsite qw< callsite context >; use Scope::Upper qw< reap UP >; my ($iterator_source) = @_; # Uniquely identify this call, according to its lexical context... my $ID = callsite() . context(); # Install the iterator... state %iterator_for; $iterator_for{$ID} //= $iterator_source->(); # Install destructor for iterator at end of caller's block... reap { delete $iterator_for{$ID} } UP UP; # Iterate... return $iterator_for{$ID}->($_[1]); } for my $limit (reverse 1..5) { while ( from{countdown($limit)} my $a ) { print "$a: "; } print "\n"; } sub countdown{ my $val = shift; my $iter = sub { if ($val--) { $_[0]=$val; return 1; } return; # stop iteration }; return $iter; }

      What the heck...I just uploaded another new release of Var::Pairs
      (version 0.004000), which lets you write this:

      use Var::Pairs; sub countdown { my $n = shift; return sub { return if $n < 0; # Indicates iterator exhausted return $n--; # Next value iterated } } for my $limit (reverse 1..5) { while (my ($a) = each_value countdown($limit)) { print $a, ':'; } say q{}; }

      ...which is very close to what you wanted, I believe.

      (And, yes, the each_value() subroutine is doing a lot of very hard paddling
      under the surface to correctly ignore all those repeated calls to countdown($limit)
      in the while loop. ;-)

      And, obviously, it would be far more efficient to write the iteration:
      for my $limit (reverse 1..5) { my $iter = countdown($limit); while (my ($a) = each_value $iter) { print $a, ':'; } say q{}; }

      Damian

        Hi Damian,

        > And, obviously, it would be far more efficient to write the iteration:

        Indeed. :-/ But it seems to work. :)

        Many thanks and sorry for the slow communication, but job is very demanding at the moment.

        ( I should have checked CPAN for "scope" and I'm not a big fan of XS dependencies but after I saw that dave_the_m is one of the maintainers, it might be canonical. ;-)

        I'll certainly have a closer look into it and will come back to it later... :)

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Wikisyntax for the Monastery

        Wouldn't it be better to wrap the hard paddle?

        sub each_value (&); ... while (my ($a) = each_value {countdown($limit)}) { print $a, ':'; }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1214136]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (6)
As of 2024-03-29 10:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found