Using next inappropriately inside a sub
Sandy
created: 2006-03-28 20:37:53
Due to my own bad coding, I have discovered another

Gotcha

(or maybe a 'got-me'?) that jumped up and bit me.

Of course, if I had had warnings on... it would have been simpler to see what was going on, ... but then on the other hand, I would not have seen this fun stuff:

#!/usr/bin/perl
use strict;
#use warnings;

for my $i (1 .. 20) {
    isodd($i);
    print "$i\n";
}

sub isodd {
    my $i = shift;
    next if int($i/2)*2 == $i;
    return;
}

gives:

1
3
5
7
9
11
13
15
17
19

Perl is so cool, but so dangerous without warnings!

Needless to say, after some refactoring, my 'next' was in a different module than my loop, and I couldn't figure out why bits of code were not being executed as expected.

UPDATE: Sorry, I meant for this to be in meditations. Can someone fix it for me??

Re: Using next inappropriately inside a sub
created: 2006-03-28 21:07:07
Sandy--

That's gotta be the funniest/scariest thing I've seen in Perl to date. Thank goodness "use warnings" picks it up.

--roboticus

Re: Using next inappropriately inside a sub
created: 2006-03-29 04:45:30
Cool! I wonder if it leaves bogus stuff on the call stack. And if after you've nexted, a return inside the for loop would go all freaky.
Re^2: Using next inappropriately inside a sub
created: 2006-03-29 05:00:45
I wonder if it leaves bogus stuff on the call stack

No, it is a supported feature.

Re^3: Using next inappropriately inside a sub
created: 2006-03-29 08:12:59

I agree. I use this feature in cgrep (see the nextfile function). The only problem with it is that loop labels are lexically scoped, not dynamically, so you can never make sure that your loop labels don't accidentally clash with those of a function you call from another module.

Re^4: Using next inappropriately inside a sub
created: 2006-03-29 09:19:40
The only problem with it is that loop labels are lexically scoped, not dynamically, so you can never make sure that your loop labels don't accidentally clash with those of a function you call from another module.
Huh? Looks dynamic to me:
#!/usr/bin/env perl
use strict;

SOME_LOOP:
for my $outer (1..2) {
  print "outer: before callback with $outer\n";
  call_my_callback( sub { next SOME_LOOP } ); # you say this should advance "$outer";
  print "outer: after callback with $outer\n";
}

sub call_my_callback {
  SOME_LOOP:
  for my $inner (1..2) {
    print "inner: before callback with $inner\n";
    $_[0]->(); # "neeeexxxt!"
    print "inner: after callback with $inner\n";
  }
}

This runs (as I expected), producing:
outer: before callback with 1
inner: before callback with 1
inner: before callback with 2
outer: after callback with 1
outer: before callback with 2
inner: before callback with 1
inner: before callback with 2
outer: after callback with 2
Note that "next" is seeing the inner loop (dynamic), not the outer loop (lexical). If it had ignored the inner loop (which you can simulate by changing the subroutine loop label to something else), the output would have been:
outer: before callback with 1
inner: before callback with 1
outer: before callback with 2
inner: before callback with 1

-- [http://www.stonehenge.com/merlyn/|Randal L. Schwartz, Perl hacker]
Be sure to read [id://205373|my standard disclaimer] if this is a reply.

perlmonks.org content © perlmonks.org and ambrus, DrHyde, merlyn, roboticus, salva, Sandy

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03