Use for elegance.





Item 7: Use $_ for elegance.

"Dollar underscore," or $_: you may love it, or you may hate it. But either way, if you're going to be a proficient Perl programmer, you've got to understand it.

$_ is a default argument for many operators, and also for some control structures. Here are some examples:

$_ as a default argument

print $_; 
print

print;

Same thing.

print "found it" if $_ =~ /Rosebud/; 
print "found it" if /Rosebud/;

Matches and substitutions.

Same thing.

$mod_time = -M $_; 
$mod_time = -M;

Most filehandle tests.

Same thing.

foreach $_ (@list) { &do_something($_) } 
foreach (@list) { &do_something($_) }

foreach

Same thing.

while (defined($_ = <STDIN>)) { print $_ } 
while (<STDIN>) { print }

while; a special case.

Same thing.

The last example illustrates the special case in which using the line input operator <filehandle> alone as the condition of a while loop is a shortcut for reading a line from the file into $_ until the end of file is reached.

This is by no means an exhaustive list. Consult the on-line documentation or your favorite comprehensive Perl reference for more information.

$_ is a normal scalar variable—mostly. You can use it, print it, change its value, and so on, just as if it were an ordinary scalar. There are a couple of things to watch out for, though.

$_ and the main package

$_ is always in the package main. This applies even, or especially, if you are in some other package:

package foo; 
$_ = "OK\n"; 
package main; 
print;

This still means $main::_.

Prints OK.

In fact, all special variables ($-punctuation) have this property. You can use a variable like $foo::_ if you like, but it has no special properties and isn't "the" $_.

Localizing $_

$_ can only be localized using local. You cannot use my. The following won't work, no matter where or how you try it:

my $_;

ILLEGAL

Programming style and $_

Oddly enough, when you use $_, you may not see much of it:

while (<>) { 
  for (split) { 
    $w5++ if /^\w{5}$/ 
  } 
}

Count all the 5-letter words.

@small_txt = grep 
  { /\.txt$/ and (-s) < 5000 } 
    @files;

Find files ending in .txt and less than 5,000 bytes long.

Some Perl programmers may feel that $_ is more an aid to obfuscation than elegance. I have a book on my shelf that opines: "Many Perl programmers write programs that have references to $_ running like an invisible thread through their programs. Programs that overuse $_ are hard to read and are easier to break than programs that explicitly reference scalar variables you have named youself." I find this hard to accept. Is:

while (defined ($line = <STDIN>)) { 
  print $line if $line =~ /Perl/ 
}

really superior to:

while (<STDIN>) { print if /Perl/ }

You'll have to decide.


     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows