in reply to stoping and restarting a loop

Here's one way that you should be able to adapt for your needs.

#! perl -sw use strict; my @data = <DATA>; my ($type3total, $type4total) = (0,0); my $state = ''; for (@data) { chomp; my ($part1, $part2) = split; if ($state eq "type4" && $part1 eq "3") { process( $type3total, $type4total ); ($type3total, $type4total) = (0,0); } $state = "type$part1"; $type3total += $part2 if ($part1 == 3); $type4total += $part2 if ($part1 == 4); die "array contains a type 7 record\n" if $part1 == 7; } process( $type3total, $type4total ); sub process { my ($type3, $type4) = (shift, shift); print "Processing type 3 total of $type3 and a type 4 total of $ty +pe4\n"; return; } __DATA__ 3 200 4 50 3 100 3 100 3 100 4 50 4 25

Gives:

C:\test>196448 3 - 200 4 - 50 3 - 100 Processing type 3 total of 200 and a type 4 total of 50 3 - 100 3 - 100 4 - 50 4 - 25 Processing type 3 total of 300 and a type 4 total of 75

Well It's better than the Abottoire, but Yorkshire!

Replies are listed 'Best First'.
Re^2: Stopping and restarting a loop
by tadman (Prior) on Sep 10, 2002 at 03:55 UTC
    A fine answer, functionally, but what's with this shift, shift action? It would be more concise, I think, to simply express it as this:
    sub process { my ($type3, $type4) = @_; print "Processing type 3 total of $type3 and a type 4 total of $ty +pe4\n"; return; }
    Maybe I'm just overly sensitive about shift. Still, with Perl 6 moving towards a full argument declaration, it will be a lot easier to migrate than shift-riddled code.

      In the original code I used $_[0] and $_[1], I changed that and gave the vars names simply to make it clearer to the OP.

      Why (shift,shift)? Why not? It makes it clear that I am only going to consider using 2 parameters. Admittely that can be derived from the left-hand side of the expression, but what is wrong with shift? The docs don't indicate that it is depreciated or anything.


      Well It's better than the Abottoire, but Yorkshire!
        It's not deprecated, in fact, it's very useful. But just because you can use a screwdriver to stir paint doesn't mean you should (JBYCDMYS, the complement to TMTOWTDI). The thing that cheeses me off about shift is that it actually modifies @_. Not that I care in most cases, but it seems like wasted effort, and programs are supposed to be efficient.

        I find a few cases where shift is handy, though, such as in these highly simplified examples:
        sub new { my $class = shift; my $self = bless ({ @_ }, $class); # Hash-style params return $self; } sub fooge_default { my $self = shift; $self->fooge(@_); # Blind parameter passing }
        In most cases, though, you can just do direct assignment, mapping your params to @_ in a single declaration. If you have some sort of sick monstrosity that takes so many paramters you have to split up the declaration on to two lines, maybe you should re-think your interface. Once you're past six arguments, things get hard to parse.

        As an example where shift is dangerous, consider this:
        sub fooge { my ($foo, $bar) = (shift, shift); die "fooge() needs two arguments\n" unless (defined($bar)); # ... }
        What's wrong with this? What if undef was a valid parameter? You've destroyed the evidence, so to speak. I'd try to use this instead:
        sub fooge { my ($foo, $bar) = @_; die "fooge() needs two arguments\n" unless (@_ == 2); # ... }
        This version distinguishes between undef and not provided.