Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re: next and last within subs

by toolic (Bishop)
on Jul 11, 2014 at 19:38 UTC ( [id://1093294]=note: print w/replies, xml ) Need Help??


in reply to next and last within subs

Could you show a little more context? Is that snippet in a sub which is called from a for loop?

If you're really sure of what you're doing, you could locally disable the warnings (perllexwarn):

use warnings; use strict; foo($_) for 1 .. 5; sub foo { no warnings 'exiting'; my $z = shift; print "$z\n"; last if $z > 2; } __END__ 1 2 3

Replies are listed 'Best First'.
Re^2: next and last within subs
by xorl (Deacon) on Jul 11, 2014 at 19:58 UTC
    This is basically what i'm doing. The other problem with exiting the sub with next or last is that it seems to completely exit the loop when at least in two cases I want to just move on to the next iteration.
    foreach (@array) { if ($something) { # do stuff if ($something1) { # time to move to next iteration of loop before_next_stuff(); } } if ($somethingelse) { # do some other stuff before_next_stuff(); } # more stuff in loop before_next_stuff(); } sub before_next_stuff { # lots o stuff if ($x > $stop) { last; } elsif ($y ne $text) { foobar(); } else { next; } }
      Trying to control a loop from a subroutine called from inside the loop is just asking for trouble. It might seem like it will work... it might even work in some circumstances... but most likely it's just going to fail. Can you see how Perl is confused by your instructions? Basically, you're trying to use a subroutine for loop control when you should be doing some form of nesting, and leave loop control inside the loop:

      sub before_next_stuff { # lots o stuff } MAINJOB: foreach ( @array ) { if ( $something ) { # do stuff if ( $something_1 ) { # time to move to next iteration # of the loop before_next_stuff(); # you should only include this # loop control here if you must if ( $x > $stop ) { last MAINJOB; } elsif ( $y ne $text ) { foobar(); } else { next MAINJOB; } } } if ( $something_else ) { # do some other stuff before_next_stuff(); # you should only include this # loop control here if you must if ( $x > $stop ) { last MAINJOB; } elsif ( $y ne $text ) { foobar(); } else { next MAINJOB; } } # more stuff in loop before_next_stuff(); if ( $x > $stop ) { last MAINJOB; } elsif ( $y ne $text ) { foobar(); } # no "next" necessary here }


      A big part of effective and elegant programming is to structure your loops so that controlling them is mostly a matter of natural flow. However, there are times when "natural flow" is simply impossible, and you need some way of interrupting loop flow -- which is why Perl has next and last functions. But they should still be used as sparingly as possible.

      Bottom line: loop control should never be farmed out to a sub external to the loop. You can abstract everything else out into subs, but control needs to stay internal.

      PS- Any time I have nested or complex loops, I use explicit labels (like "MAINJOB", above). They help both Perl and me (much more me than Perl) keep track of which loop is being controlled at any given time.

      Sounds like you want to return from the sub, rather than try to manipulate the loop outside the sub.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2024-04-25 14:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found