Your question about print in foreach will be answered, here is a bit more on $_ .
From General Variables in perlvar
Here are the places where Perl will accept $_ , even if you are not using it:
The following functions use $_ as the default argument:
- abs, alarm, chomp, chop, chr, chroot, cos, defined, eval, evalbytes, exp, fc, glob, hex, int, lc, lcfirst, length, log, lstat, mkdir, oct, ord, pos, print, printf, quotemeta, readlink, readpipe, ref, require, reverse (only in a scalar context), rmdir, say, sin, split (for the second argument), sqrt, stat, study, uc, ucfirst, unlink, unpack.
All file checks ( -f , -d ), except for -t , which defaults to STDIN. See -X
Pattern matching operations m// , s/// and tr/// (aka y/// ) when used without the operator =~ .
The default iterator variable in the foreach , unless another variable is specified.
The implicit iterator variable in grep() and map() .
Implicit variable given() .
The default location for placing the next value or input record when the result of the <FH> , readline , readdir or each operation is checked by itself as the only criterion for the while test. Outside of the while tag, this will not happen.
$_ is a global variable by default.
As you can see, it is available almost everywhere, and it is really used a lot. Note that the perlvar page describes a lot more similar variables, many of which are well known.
Here is an example. Think that we are reading lines from a file, we want to discard those that have only spaces, or begin with # (comments), and for others, separate them with spaces into words.
open my $fh, '<', $file or die "Can't open $file: $!"; while (<$fh>) { next if not /\S/; next if /^\s*
Let's see how many uses of $_ are in the above example. Here is the equivalent program
while (my $line = <$fh>) { next if not $line =~ m/\S/; # if not matching any non-space character next if $line =~ m/^\s*#/; # if matching # after only (possible) spaces my @words = split ' ', $line; # split $line by ' ' (any white space) # do something with @words ... }
Compare these two
the file identifier read <$fh> in while assigns the $_ condition available in the loop.
The regex matching operator defaults to $_ . m itself can be discarded.
split by default splits $_ . We also use a different default value, because the pattern breaks the string into ' ' (any amount of any space).
as soon as we do $line = <$fh> deal with $_ off (it is undefined in the loop), and we should use $line everywhere. So either do this or do while (<$fh>) and use $_ .
To illustrate all this a bit further, we find the longest headword on each line
use List::Util 'max'; my $longest_cap = max map { length } grep { /^[AZ]/ } @words;
grep takes the list in @words and applies a block to each element. Each element is assigned $_ and, therefore, is available for code inside the block as $_ . This is what regex uses by default. Those that satisfy the condition are passed to map , which also iterates over, assigning them $_ , which of course is the default value for length . Finally, max from List :: Util selects the largest.
Note that $_ never written and no temporary variable is required.
Here are some of the relevant documents. Perlop 's I / O statements discuss while (<$fh>) and all sorts of related things. Part of the regular expression is in the Regexp Quote-Like Operators in perlop and in perlretut . Also see split .
The default values are used regularly and for reading code written by others, you should understand them. When you write your own code, you can choose whether to use $_ or not, since you can always enter a lexical variable instead.
So, when to use $_ by default (which does not need to be written), and if not?
The proper use of the default values, $_ in particular, can lead to clearer and more understandable code. Which generally means better code. But it is possible to push it too far and end with a dark, complex and fragile code. Good taste is needed.
Another case is that some parts of the code benefit from $_ for their default values, while in other places you need to explicitly use $_ . I would say that if $_ visible more than once or twice in a section of code, it means that there should be a properly named variable instead.
In general, if in doubt, just name everything.