AFAIK the list context just allows you to declare a whole bunch of vars in one go - e.g.
my $foo; my $bar;
and
my ($foo, $bar);
are the same.
Although it's convenient that you can declare a whole lot of variables in one line, the big advantage is that you can handle assignments at the same time:
my ($foo, $bar) = @array;The only warning I can give is that using an undef in the list will throw warnings (errors?) in older versions of perl:
my (undef, $foo, undef, $bar) = @array;You can assign values from a list of scalars, as well, but I think it's less legible than assigning one at a time:
my ($foo, $bar, $baz) = (27, 'blah', $x);One common mistake that is made when assigning to a collection of scalars is this:
my ($one, $two, $three, $four) = 0;
People tend to think that all four variables are initialized, but really only $one is set to zero, the rest are still undef. You'd have to explicitly set each variable to achieve that result:
my $one = my $two = my $three = my $four = 0;
... or alternatively:
my ($one, $two, $three, $four) = (0,0,0,0);
But as was stated elsewhere, this lacks readability for large collections of scalars. In general, I tend to declare my variables and either initialize them to zero or leave them undefined, then assigning their values in later statements. I hate getting warnings about variables being undef when evaluating in a conditional statement.
(undef, my $foo, undef, my $bar) = @array;
my $foo = "ab"; (my $avar, $foo) = ($foo =~ /(.)(.)/);
I prefer slicing. Instead of:
my (undef, $foo, undef, $bar) = @array;or
(undef, my $foo, undef, my $bar) = @array;do:
my ($foo, $bar) = @array[1,3];e.g.
my ($size, $mtime) = (stat $filename)[7,9];
my ($foo, $bar) = return_an_array();
print "Foo: $foo, BAR: $bar, BAZ: $baz";
sub return_an_array() {
my @the_array = ("1","apple","a");
return @the_array;
}
Will print"One is enough. If you are acquainted with the principle, what do you care for the myriad instances and applications?"
- Henry David Thoreau, Walden
my $x and my($x) differ only when it's used on the left hand side of an assignment. In that case, when you write my $x = FOO, FOO is evaluated in scalar context, if you say my($x) = FOO, it's evaluated in list context, and the first value in the list is assigned to $x (undef if the list is empty).
A common example is a sub starting with sub { my($x) = @_; meaning that the sub would receive one argument and copy it to $x. In this case, sub { my $x = @_; wouldn't work, as it would store the number of arguments to $x.
This is, however, not specific to my: if you write an assignment like $x = FOO or ($x) = FOO, the same rules apply, only it doesn't create a new lexical variable $x but uses the existing variable.
perl -e 'my $x = "abcdefg" =~ /(cd)/; print "$x\n";'
prints
1
whereas matching in list context assigns the captures in the match
perl -e 'my ($x) = "abcdefg" =~ /(cd)/; print "$x\n";'
prints
cd
Normally, or rather probably, you would be making more than one capture in the regular expression so you would do something like
my($this, $that) = $string =~ /abc(def).+?(pq)$/;
Cheers,
JohnGG
my @x = ('a' .. 'e');
my $y = @x;
my ($z) = @x;
warn $y; # 5
warn $z; # 'a'
Because, in scalar context, an array variable will evaluate to it's length.
function foo {
my ($bar, $stuff, $blah) = @_; # get the arguments
...
}
my $elems = scalar @list;
rather than
my $elems = @list;
just to make it crystal clear for "those that come after" what is going on. That the question gets asked demonstrates why such practices can be helpful.
Cheers,
JohnGG
Another useful use of list context is with regular expression captures. Consider:
my $x = /(\w+)/;
and
my ($x) = /(\w+)/;
The first example will set $x to 1 if $_ contains any alphanumerics. The second example sets $x to the first word.
The second, list context, example is such a common, natural idiom to me that I never make the mistake of using captures in scalar context. I also almost never need to use $1, $2 etc. explicitly.
--
Oh Lord, wont you burn me a Knoppix CD ?
My friends all rate Windows, I must disagree.
Your powers of persuasion will set them all free,
So oh Lord, wont you burn me a Knoppix CD ?
(Missquoting Janis Joplin)
$ perl -le 'my $x = localtime; print $x' Tue Apr 4 11:25:49 2006 $ perl -le 'my($x) = localtime; print $x' 52
If you read the docs for localtime, you'll see that it returns different values when called in a scalar or list context, so the type of assignment can make a big difference.
Here's another example:
#!/usr/bin/perl
sub test
{
if (wantarray) { return ('list context'); }
else { return 'scalar context'; }
}
my $s = test;
print "s=$s\n";
my(@l) = test;
print "l=@l\n";
which outputs:
s=scalar context l=list context
Here's a popular use of the list context:
sub foo {
my ( $x, $y, $z ) = @_;
# ...
}
You can mix scalars with other types:
sub say {
my ( $x, %param ) = @_;
# ...
}
&say( "Hello", name => "world" );
The following example won't work as you could expect, because all the arrays will be flatenned into the same one:
sub bar {
my ( @a, @b ) = @_; # wrong!
# ...
}
&bar( @array1, @array2 ); # wrong!
The solution is to use references, but we still can use the list context:
sub bar {
my ( $a_ref, $b_ref ) = @_; # ok
# ...
}
&bar( \@array1, \@array2 ); # ok
In my experience, code full of lines like:
my ($x); my ($y); my ($i) = 1;Is usually evidence of a copy/paste programmer at work. No shame in that when you're a self taught beginner, but you don't want to be seeing it in code written by an "experienced" Perl programmer.
if you have functions or the like that behave differently in scalar or list context, there may be problems
open (my $FH, "<", $file) or die ...
# reads the whole file, assigns first line to $headline
my ($headline) = <$FH>;
# since the whole file is already read, there's nothing
# more to be read, so the while block will never be executed
while( my $line = <$FH> ) {
or:
sub xxx {
# error, must be my ($firstParam) = @_; if you don't want
# to get the number of parameters but the first param
my $firstParam = @_;
...
or reverse, localtime, caller, regular expressions,...
Best regards,
perl -e "s>>*F>e=>y)\*martinF)stronat)=>print,print v8.8.8.32.11.32"
my ($x) my $x; my $y; my $z;but if you're instantiating a bunch of items before an eval block / loop:
my ( $x , $y , $z );
my (
$x ,
$y ,
$z
);
both look cleaner to read and have a slighty faster perfomance (though its really insignficant). you can bench to see.
sub function{
my $self = @_;
}
is bad form - what if an argument is missing/extra?
sub function{
my ($self) = @_;
}
is better. because you might want
sub function{
my ($self , $arg1 , $arg2 ) = @_;
}
perlmonks.org content © perlmonks.org and ambrus, aufflick, benizi, blogical, davidrw, eff_i_g, jhourcle, johngg, Melly, nferraz, nmerriweather, ptum, Rhandom, rinceWind, sgifford, strat, tamaguchi, xorl
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03