Search code examples
perlbreaksubroutine

Run subroutine n number of times


I have this perl code below:

use strict;
use warnings;
sub powerset(&@) {
    my $callback = shift;
    my $bitmask = '';
    my $bytes = @_/8;
    {
       my @indices = grep vec($bitmask, $_, 1), 0..$#_;
       $callback->( @_[@indices] );
       ++vec($bitmask, $_, 8) and last for 0 .. $bytes;
       redo if @indices != @_;
    }
}

powerset { print "[@_]\n" } 1..21;

I'm trying to figure out how I can only run n times (say 6 times the powerset subroutine). i tried use it:

   $x = 0;
        while ($x <= 6) {
            $x ++;
            powerset() ;
                
        }

On run 6 times I mean run to the sixth printed line, in this case to powerset {print "[@_]\n"} 1..21; matches up to the impression of

   []
    [1]
    [2]
    [1 2]
    [3]
    [1 3]
    [2 3]

But I don't know where I would apply it $x = 0; while ($x <= 6) { $x ++; powerset() ; }, if inside the sub powerset() or outside, it seems to me that inside the sub because where the routine is happening.

i know i should use die or return to get out of running a subroutine and that somewhere in while i should use maybe else, but i still don't see how to structure this in the code.

I feel that I should better understand the function of the variables $bitmask, $bytes, $callback, because as it is a lazy evaluation, the way of counting the execution is different.

Further research on how to run a perl subroutine leads me to questions about using timers that depend on the elapsed time in seconds rather than the number of times the subroutine is executed.


Solution

  • Here is an example of how you can constrain the number of times the callback is called:

    use feature qw(state);
    use strict;
    use warnings;
    
    sub powerset(&@) {
        my $callback = shift;
        my $bitmask = '';
        my $bytes = @_/8;
        {
            my @indices = grep vec($bitmask, $_, 1), 0..$#_;
            $callback->( @_[@indices] );
            ++vec($bitmask, $_, 8) and last for 0 .. $bytes;
            redo if @indices != @_;
        }
    }
    
    my $limit = 6;
    powerset
      {
          state $counter = 0;
          die "limit reached" if ++$counter > $limit; 
          print "[@_]\n"
      }
      1..21;