I think the subroutine is cleaned up okay, but it's still rather presumptous
of the subroutine to decide it was called from within a loop. And note that
"next" is more or less equivalent to a return if there is a return statement
in the subroutine, since return is implemented internally using a BLOCK.
You'd still be able to say "next FILE", or whatever.
Guess what this does:
sub foo {
return unless @_;
print "I say, ";
while ($_ = shift) {
redo _SUB_ if /^;$/;
print $_," ";
}
}
&foo(now,is,';',the,time);
Larry
for (1..5) {
print "before $_...\n";
&marine();
print "after $_...\n";
}
sub marine {
print "begin marine\n";
next; #################### look here
print "end marine\n";
}
which prints:
before 1...
begin marine
before 2...
begin marine
before 3...
begin marine
before 4...
begin marine
before 5...
begin marine
Yow! The next exits the sub and cycles the outer "for" loop! (This
bit me in a program today.)
I suspect that the "next" (as well as a last or redo) should be a
syntax error at this point. I can't see why loop control statements
should affect something out-of-scope.
Does anyone currently use this (mis-)feature in a positive way? If
not -- Larry, could you see about flagging this as an error?
sub a {next;} {&a; redo;} print "Just another Perl hacker,"
--
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III |
| mer...@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel: putting the 'backward' in 'backward compatible'..."====/
I say leave it in. This is like catch/throw or setjmp/longjmp.
As long as the subroutines are cleaned up ok, I'm all for it.
--
[rbj@uunet 1] stty sane
unknown mode: sane
Boo. Hiss. This is too easy to screw up, and not flexible
enough for exception handling. That's what eval/die give you.
--tom
--
I get so tired of utilities with arbitrary, undocumented,
compiled-in limits. Don't you?
Tom Christiansen tch...@convex.com convex!tchrist
I often use the aformentioned feature as follows:
sub err { print STDERR "$f: $_[0]: @!\n"; next; }
for $f (@files) {
open(FILE, $f) || &err("open");
print FILE "something\n" || &err("print");
close(FILE) || &err("close");
}
You could turn this into one expression or put a next on every line.
However, I always take Larry's advice: "Perl is designed to give
you several ways to do anything, so consider picking the most
readable one." BTW, why doesn't "next $l" work?
$_='$_="Just another Perl";redo';{eval;$_.=' hacker,';}s,\S+\,,\U$&,,print;
Rob nag...@olsen.ch
sigh. probably can't get rid of it then.
still, it gives me the willies.
:
:sub err { print STDERR "$f: $_[0]: @!\n"; next; }
you mean, $!, not @!, i think.
:for $f (@files) {
: open(FILE, $f) || &err("open");
: print FILE "something\n" || &err("print");
: close(FILE) || &err("close");
:}
:
:You could turn this into one expression or put a next on every line.
:However, I always take Larry's advice: "Perl is designed to give
:you several ways to do anything, so consider picking the most
:readable one." BTW, why doesn't "next $l" work?
(do you mean "next $f"?)
one answer is that next takes a label as an operand, not a scalar.
as for why this should be so, i dunno -- ask larry. :-)
--tom
This is bad, because there no way to know this unless you
hack on perl's innards.
>You'd still be able to say "next FILE", or whatever.
This is almost equivalent to a catch/throw pair!
>Guess what this does:
>
sub foo {
return unless @_;
print "I say, ";
while ($_ = shift) {
redo _SUB_ if /^;$/;
print $_," ";
}
}
&foo(now,is,';',the,time);
It doesn't print: "I say, now is I say, the time" :-)
What are the rules for naming these blocks. Are they all called _SUB_?
Why not call them _FOO_, _BAR_, etc?
>Larry
Tom Christiansen sez:
>
>Boo. Hiss. This is too easy to screw up, and not flexible
>enough for exception handling. That's what eval/die give you.
As mentioned above, tis more or less catch/throw. And I'm
reluctant to use eval/die for this. Actually, eval/die is less
powerful than catch/throw or setjmp/longjmp, as there is only one
possible return point with the eval/die. Also, I am reluctant to
use eval often, even in LISP. I find the scoping slightly more
difficult to figure out.
It's no different than at any other time: it's dynamic, which
means you can see something if your caller could. This is
what often confuses people, most of whom are used to lexical
scoping. Of course, once you bring pass-by-reference and
pass-by-name into the picture, you quickly find yourself caught
it a maze of twisty, turn pathways, all alike.
--tom
Actually, I prefer dynamic scoping over lexical scoping.
I guess I was trying to convince myself that using eval
produced a third kind of scope, but I guess not.
If I allowed "next $label" then I'd also have to allow "goto $label", and
I don't think you really want that... :-)
Besides, you can always say
eval "next $label";
:-)
Larry