Re: <STDIN> not initializing $_
by pc88mxer (Vicar) on Apr 30, 2008 at 23:05 UTC
|
Yes, while (<STDIN>) { ... } is special in that it:
- Reads a line from STDIN
- Assigns the line to $_
- Exits the loop if STDIN was at EOF before the read
Invoking <STDIN> by itself just reads a line but doesn't automatically assign it to $_.
Note that this is different from merely testing whether or not $_ is true as is shown by this example:
$/ = "0";
while (<DATA>) {
print "got $_ and it ", ($_ ? "is" : "is not"), " true\n";
}
__END__
00000
which emits:
got 0 and it is not true
got 0 and it is not true
...
| [reply] [d/l] [select] |
Re: <STDIN> not initializing $_
by oko1 (Deacon) on May 01, 2008 at 00:41 UTC
|
The part that you may be missing is that '$_' is not created by <STDIN> - it's created as a result of the 'while' loop, in the same way that it would be created if you'd used a 'for' loop.
while (<STDIN>){ # Loops over <STDIN> as long as it returns '
+true'
print;
}
while ($_ = <STDIN>){ # Exact equivalent of the above but "spelled
+ out" explicitly
print $_; # Ditto for this line - exactly equvalent to
+ a simple 'print;'
}
for (1,2,3){ # Loop over specified list
print; # Print out each item (which has been assign
+ed to $_) in turn
}
for $_ (1,2,3){ # Exact equivalent of the above but "spelled
+ out" explicitly
print $_; # Same story
}
In general, whenever you see a variable being omitted (e.g., 's/foo/bar/' instead of '$xyz =~ s/foo/bar/'), '$_' is being used. It's part of the standard Perl idiom, and you need to get familiar with it. At the very least, you'll need it to read other people's code.
--
Human history becomes more and more a race between education and catastrophe. -- HG Wells
| [reply] [d/l] |
|
|
>perl -MO=Deparse -e"while (<STDIN>) {}"
while (defined($_ = <STDIN>)) {
();
}
-e syntax OK
>perl -MO=Deparse -e"while ($_ = <STDIN>) {}"
while (defined($_ = <STDIN>)) {
();
}
-e syntax OK
| [reply] [d/l] [select] |
|
|
Note that the implicit "$_ = " in a while/until expression is only added for <>, readline, or glob operations.
There's an implicit defined() also, as ikegami notes, but that's broader. It
is added when the while/until condition is a scalar assignment (itself possibly implicit as noted above) from a <>, readline, glob, readdir, or each operation.
| [reply] |
|
|
Thank you all, monks, for your insights regarding my question. I'm currently in the process of reading "Programming Perl". Today I discovered the book explicitly explains <> and $_. It also confirms your answers, especially ysth's. The first part of `Line Input (Angle) Operator' in `Input Operators' in Chapter 2 covers the subject thoroughly. A short quote:
If and only if the line input operator is the only thing inside the conditional of a while loop, the value is automatically assigned to the special variable $_.
After that some useful examples follow.
| [reply] [d/l] [select] |
|
|
perl -le"while ($a=0) { print 'ysth is right'; last }"
Tested with Perl 5.6.0, 5.6.1, 5.8.0, 5.8.8, 5.10.0.
| [reply] [d/l] |
|
|
|
|
Re: <STDIN> not initializing $_
by wade (Pilgrim) on Apr 30, 2008 at 23:22 UTC
|
Yeah, and since $_ can get silently overwritten (especially as you add code and forget that you were counting on $_) I really hate to use it. Instead, I assign everything to my own variables:
use strict;
use warnings;
while (1) {
my $foo = <STDIN>;
$foo =~ m/./ and print "success.\n";
# ... (more code) ...
}
I'd also tend not to use a while(1) loop but that's a whole other Oprah.
| [reply] [d/l] [select] |
|
|
> Yeah, and since $_ can get silently overwritten [...]
Just about as silently as every other variable in Perl. No matter what your own preferences may be, '$_' is an important and integral part of Perl - and there's no reason to give misleading advice to someone who is trying to learn about it.
> [...] I really hate to use it.
Say 'goodbye' to grep and map, then. In fact, bid 'good night' to half the functionality of most Perl functions.
--
Human history becomes more and more a race between education and catastrophe. -- HG Wells
| [reply] |
|
|
I'm just saying that I like to assign values to variables explicitly when possible. I think it's clearer and a little less error-prone but that's just me.
| [reply] |
Re: <STDIN> not initializing $_
by FunkyMonk (Bishop) on May 04, 2008 at 23:45 UTC
|
I'm late coming in with this, sorry:(
If while (<STDIN>) does something you don't expect, the Perl documentation should be your first port of call. You can...
- google for perldoc while
- search for while at http://perldoc.perl.org
- Use perldoc perlsyn from the command line (unfortunately you need to know that while's described in perlsyn)
- If you're using ActivePerl on windows, Perl's documentation can be accessed via Start -> Programs -> ActivePerl -> Documentation.
| [reply] [d/l] [select] |