Dollar Underscore

A PerlLanguage feature. $_ is an implicit local variable which holds the result of the last function/builtin called. So it's really easy to chain together functions and builtins without naming a whole bunch of variables. PythonLanguage has no equivalent ... right? Can be found in RubyLanguage though.

Right. PythonLanguage has a variable called _ which is set to the result of the last statement executed. However, it is only there in interactive mode, and really doesn't do the same thing as $_.


Ugh! That's not what it is at all. $_ is the "default input and pattern searching space". It contains lines you read in, unless you say otherwise, and it's what regular expressions search over, unless you say otherwise. There are other uses (e.g., the default iterator variable in a for() loop).

http://www.perl.com/CPAN-local/doc/manual/html/pod/perlvar.html#item__

$_ can lead to very concise and readable code; it can also lead to very terse and ugly code. Unfortunately, you have to know which is which.


Is this a bug or a feature? Sometimes I rewrite perl code to use explicit variables instead. It seems clearer that way.

Sometimes you can't escape the magic in perl, for example when using map {} - theres no way to say what the loop variable is. (You could always drop back to using for my $x (){} I suppose). Currently the only way out of writing stuff like

  sub cat {@ARGV=@_[$[..$#_]];print <>;} 

(hey - its a joke) is to 'use English', and then actually use those names. But see my comments on http:/w4/wikibase/?DollarAmpersand on why that is still a bad idea.


Uh, maybe I'm missing the joke, but what do you prove by using such obfuscated code in your example? The answer is, of course, DontDoThat!

For the information of any non-perl programmers who might be interested, the above could have been written as:

sub cat { print @_ }

... with no loss in functionality.

Sorry Skud, it couldn't, but the original function has bad voodoo in it since it overwrites @ARGV without localizing it. If you insist on using magic to get the functionality then

sub cat {
local(@ARGV) = @_;
print <ARGV>;
}

is better style and should be reasonably easy for a perl programmer to understand but I'd definitely not be happy to see any of my team writing it like that.

sub cat {
foreach my $file (@_) {
open my $fh, '<', $file or die "Couldn't open $file: $!";
print $lines while defined(my $line = <$fh>);
}
}

Is more explicit, expresses the intention better and doesn't use anywhere near as much memory.

-- PiersCawley

The main problems with DollarUnderscore are:

  foreach my $pet (keys %pets) {
foreach my $food (keys %petfoods) {
feed($pet, $food);  # obviously feed($_, $_) wouldn't work here
}
  }

sub foo {
my @params = @_;
print "First param is $params[0]\n";# not $_[0]
print "Last param is $params[$#params]\n";  # not $_[$#_]
}

-- KirrilyRobert

This is a rather nice idiom: I disagree.

sub foo {
my ($bar, $baz, ) = @_;
...
}

it almost fixes perl's function declarations to look like some more rational language. Actually being unable to name function arguments is a real bug, IMHO.


CategoryPerl


EditText of this page (last edited December 24, 2010) or FindPage with title or text search