Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

my $x or my ($x)

by tamaguchi (Pilgrim)
on Apr 04, 2006 at 11:59 UTC ( [id://541132]=perlquestion: print w/replies, xml ) Need Help??

tamaguchi has asked for the wisdom of the Perl Monks concerning the following question:

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

Replies are listed 'Best First'.
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.

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

Re: my $x or my ($x)
by Melly (Chaplain) on Apr 04, 2006 at 12:07 UTC

    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

      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.


        No good deed goes unpunished. -- (attributed to) Oscar Wilde
        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)
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 ... }
      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)
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.

      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)
by rinceWind (Monsignor) on Apr 04, 2006 at 14:26 UTC

    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)
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
    
Re: my $x or my ($x)
by nferraz (Monk) on Apr 04, 2006 at 18:53 UTC

    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)
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"

Re: my $x or my ($x)
by Bod (Parson) on Jan 02, 2021 at 22:47 UTC

    This has just caught me out in a while loop for getting information from a database

    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; }
      > 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.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

      °) see also Re: list context (iterators)

        Because the iterator ->fetchrow_hashref returns one scalar undef when done

        Usually I use fetchrow_array - I don't think I have used fetchrow_hashref before.

        The problem came because I was converting from this code

        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.

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.
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 ) = @_; }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://541132]
Approved by tbone1
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (3)
As of 2024-03-19 04:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found