my $x or my ($x)
tamaguchi
created: 2006-04-04 07:59:00
It is possible to decleare a variable by 'my' as:

my $x

or

my ($x)

If in the universal perl book "Learning Perl", by Randal L. Schwartz, Tom Phoenix, it is stated that the second exaple decleares the variable in a "list" content. But it is not explained very well why one would like to decleare variables in "list content". I wonder therefore when it is good to decleare variables in the first way and when it is more appropiate to decleare them in the second way. What implications would it have to decleare all vairables, in a larger program in list content;
"my ($x)"
, regardless if it is needed or not. Would it be negative in some way? Thank you for any help
Re: my $x or my ($x)
created: 2006-04-04 08:07:12

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.

Tom Melly, tom@tomandlu.co.uk
Re^2: my $x or my ($x)
created: 2006-04-04 08:15:56

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);
Re^3: my $x or my ($x)
created: 2006-04-04 09:39:51

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.


No good deed goes unpunished. -- (attributed to) Oscar Wilde
Re^4: my $x or my ($x)
created: 2006-04-04 11:35:03
Just a quick addition to [ptum]'s. I would write:
my ($one, $two, $three, $four) = (0,0,0,0);
as
my ($one, $two, $three, $four) = (0) x 4;
Re^3: my $x or my ($x)
created: 2006-04-05 11:06:56
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;


Never fear. Just move your my.
(undef, my $foo, undef, my $bar) = @array;

This is particularly more useful in cases where you already have a declared variable.
my $foo = "ab";
(my $avar, $foo) = ($foo =~ /(.)(.)/);


my @a=qw(random brilliant braindead); print $a[rand(@a)];
Re: my $x or my ($x)
created: 2006-04-25 11:45:15

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];
Re: my $x or my ($x)
created: 2006-04-04 08:13:13
In addition to the above, the list context can be useful in a case like this:
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
Foo: 1, BAR: apple, BAZ: a
Re^2: my $x or my ($x)
created: 2006-04-04 13:49:19
Or it would, if you asked for $baz. As it is it simply discards the third return item, 'a'.

"One is enough. If you are acquainted with the principle, what do you care for the myriad instances and applications?"
- Henry David Thoreau, Walden

Re: my $x or my ($x)
created: 2006-04-04 08:14:57

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.

Re: my $x or my ($x)
created: 2006-04-04 08:47:57
Another place where the effect of my $x; and my ($x); differs is in matching regular expressions. Assigning a match in scalar context just records whether the match was successful, like this

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

Re: my $x or my ($x)
created: 2006-04-04 09:24:34
for the behavior, besides all of the above posts, also consider this simple example:
  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.

I'd say that, in general, it's "more appropriate" to declare in list context only when list context is actually needed -- e.g. declaring multiple variables at once, or sometihng like the my ($z) = @x; above where you're working w/ an array on the RHS.

Another common use of list context:
function foo {
  my ($bar, $stuff, $blah) = @_;   # get the arguments
  ...
}
Re^2: my $x or my ($x)
created: 2006-04-04 12:45:33
I know that it is really not necessary but I have got into the habit when counting elements in a list of doing

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

Re: my $x or my ($x)
created: 2006-04-04 10:26:16

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, won’t 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, won’t you burn me a Knoppix CD ?
(Missquoting Janis Joplin)

Re: my $x or my ($x)
created: 2006-04-04 11:31:57
The variable itself isn't in a list context; whatever comes after the equal sign is in a list context. Regular expression matches are one place where this matters, but here's a clearer example:
$ 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
Re: my $x or my ($x)
created: 2006-04-04 14:53:40

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
Re: my $x or my ($x)
created: 2006-04-05 01:14:28
Slightly related...

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.
Re: my $x or my ($x)
created: 2006-04-05 04:08:32

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"

Re: my $x or my ($x)
created: 2006-04-05 15:11:50
if you're declaring 1 variable, its convoluted and a mess to do
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.

also: if you're doing oop perl:
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