Re: my $x or my ($x)
by ambrus (Abbot) on Apr 04, 2006 at 12:14 UTC
|
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.
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: my $x or my ($x)
by johngg (Canon) on Apr 04, 2006 at 12:47 UTC
|
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 | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: my $x or my ($x)
by Melly (Chaplain) on Apr 04, 2006 at 12:07 UTC
|
my $foo;
my $bar;
and
my ($foo, $bar);
are the same.
Tom Melly, tom@tomandlu.co.uk
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
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);
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
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
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
|
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)];
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Re: my $x or my ($x)
by davidrw (Prior) on Apr 04, 2006 at 13:24 UTC
|
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
...
}
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
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 | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: my $x or my ($x)
by xorl (Deacon) on Apr 04, 2006 at 12:13 UTC
|
In addition to the above, the list context can be useful in a case like this:
my ($foo, $bar, $baz) = 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
Update: added $baz in the correct place. Thanks blogical.
| [reply] [Watch: Dir/Any] [d/l] |
|
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
| [reply] [Watch: Dir/Any] [d/l] |
Re: my $x or my ($x)
by rinceWind (Monsignor) on Apr 04, 2006 at 14:26 UTC
|
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)
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: my $x or my ($x)
by sgifford (Prior) on Apr 04, 2006 at 15:31 UTC
|
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
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: my $x or my ($x)
by nferraz (Monk) on Apr 04, 2006 at 18:53 UTC
|
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
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: my $x or my ($x)
by strat (Canon) on Apr 05, 2006 at 08:08 UTC
|
If you just write my $x; or my ($x); there is no important difference
but if you assign values to the variable and have functions or the like that behave differently in scalar or list context, there may be problems, e.g.
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:
my $x = reverse('abcdef');
my ($y) = reverse('abcdef');
print "x=$x\ny=$y\n";
or localtime, caller, regular expressions,...
Best regards,
perl -e "s>>*F>e=>y)\*martinF)stronat)=>print,print v8.8.8.32.11.32"
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: my $x or my ($x)
by Bod (Parson) on Jan 02, 2021 at 22:47 UTC
|
my $query = $dbh->prepare("SELECT idFrame, name, colour FROM F
+rame");
$query->execute();
while (my ($frame) = $query->fetchrow_hashref) {
push @frames, $frame;
}
This loop never ends!
Although $query->fetchrow_hashref returns undef once all the rows have been returned, the condition as whole doesn't so the loop continues...
This is what I really wanted (and how have)
my $query = $dbh->prepare("SELECT idFrame, name, colour FROM F
+rame");
$query->execute();
while (my $frame = $query->fetchrow_hashref) {
push @frames, $frame;
}
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
> This loop never ends!
Because the iterator ->fetchrow_hashref returns one scalar undef when done. But a list assignment (...) = ... is only false if the list is empty. °
It might have been better to return an empty list. This would have worked similarly well in list as scalar context.
But it's only supposed to return one scalar - the mentioned hashref - anyway.
°) see also Re: list context (iterators)
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
my @frames;
my $query = $dbh->prepare("SELECT idFrame, name, colour FROM Frame
+");
$query->execute();
while (my ($id, $name, $colour) = $query->fetchrow_array) {
my $frame = {
'image' => 'test_thumb.jpg',
'id' => $id,
'name' => $name,
'colour' => $colour,
};
push @frames, $frame;
}
my $vars = {
'frames' => \@frames,
};
$template->process("admin_frames.tt", $vars);
It seemed silly to me to be fetching the elements of an array, using those to build an anonymous hash and adding the reference to it to an array. Why not just fetch the hashref and add that to the array?
my @frames;
my $query = $dbh->prepare("SELECT idFrame, name, colour FROM Frame
+");
$query->execute();
while (my ($frame) = $query->fetchrow_hashref) {
$$frame{'image'} = 'test_thumb.jpg';
push @frames, $frame;
}
my $vars = {
'frames' => \@frames,
};
$template->process("admin_frames.tt", $vars);
Finding the error of my ($frame) = $query->fetchrow_hashref instead of my $frame = $query->fetchrow_hashref took some time. Not helped by developing it on a webserver so when the loop didn't end, I assumed the connection was just being ultra slow!
I suspect that there is a more elegant solution that doesn't involve iterating through the rows from the database using fetchall_hashref but that's (possibly) for another day. There will only ever be a handful of rows returned by this query. | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: my $x or my ($x)
by aufflick (Deacon) on Apr 05, 2006 at 05:14 UTC
|
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. | [reply] [Watch: Dir/Any] [d/l] |
Re: my $x or my ($x)
by nmerriweather (Friar) on Apr 05, 2006 at 19:11 UTC
|
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 ) = @_;
}
| [reply] [Watch: Dir/Any] [d/l] [select] |