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

Exiting subroutine via next

by InfiniteLoop (Hermit)
on Dec 07, 2006 at 03:58 UTC ( [id://588253]=perlquestion: print w/replies, xml ) Need Help??

InfiniteLoop has asked for the wisdom of the Perl Monks concerning the following question:

Greetings Monks,
  My question is related to this post next'ing out of a "foreach" loop within a subroutine. Take this code:
sub foo { my $param = shift; if ($param eq "skip") { next; } } foreach my $var (1, 2, 3, "skip", 4) { foo($var); print $var; }
 I was expecting perl to throw me an error for using next to return from a sub{} , however it doesn't happen so. (although I could get a warning, if I use the -w flag). Also next, says:
"next" cannot be used to exit a block which returns a value such as "eval {}", "sub {}" or "do {}"...

My question is: why this behaviour ? what is the logic behind it ? wouldn't it be beneficial if the interpreter threw a error for invalid use of next, in this case ? (I have tested this code under perl v5.8.6)

Replies are listed 'Best First'.
Re: Exiting subroutine via next
by ikegami (Patriarch) on Dec 07, 2006 at 06:41 UTC

    My question is: why this behaviour ?

    I believe that's it's implemented at its simplest. next, last and redo simply locate the closest frame on the stack that supports the operation. Doing anything different would require extra work.

Re: Exiting subroutine via next
by ysth (Canon) on Dec 07, 2006 at 06:44 UTC
    why this behaviour ? what is the logic behind it ? wouldn't it be beneficial if the interpreter threw a error for invalid use of next, in this case ?
    It's something you shouldn't do without a good reason, hence the warning, but why do you want it to throw an error by default?

    In any case, you can use warnings 'all', 'FATAL' => 'exiting'; if that's to your liking.

Re: Exiting subroutine via next
by geekphilosopher (Friar) on Dec 07, 2006 at 05:56 UTC

    I'm not sure, but pg's comment in the referenced thread talks about how semantically a sub is a block in the scope of where it was called (with differences of course, such as not seeing lexicals of the containing scope). Since next just looks up the scope change for the nearest encasing block, which in this case is the foreach.

    I don't really know how to explain the quoted documentation though. I just edited your function to include a return statement, and it still worked the same way.

      I don't really know how to explain ["next" cannot be used to exit a block which returns a value such as "eval {}", "sub {}" or "do {}"...]

      It means next, last and redo ignore do blocks, eval blocks, etc. They will only cause loop blocks and bare blocks to repeat, exit, etc. It makes more sense when you read that same line in the documentation for last, since next doesn't cause a loop to exit.

      foreach my $var (1, 2, 3, "skip", 4) { eval { # This block is ignored. if ($var eq "skip") { next; } }; print $var; } print("\n"); foreach my $var (1, 2, 3, "skip", 4) { { # This block exits. if ($var eq "skip") { next; } } print $var; } print("\n");

      outputs

      1234 123skip4
        Ah, that makes sense. Thanks!
      I don't really know how to explain the quoted documentation though. I just edited your function to include a return statement, and it still worked the same way.
      The (poorly worded) documentation doesn't mean next won't leave that scope - it just means you can't use next to resume execution just after of the current eval {}, etc. when there's no loop in the eval {}, etc.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (8)
As of 2024-04-18 11:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found