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

when is "my" not necessary?

by argv (Pilgrim)
on Nov 02, 2004 at 19:53 UTC ( [id://404730]=perlquestion: print w/replies, xml ) Need Help??

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

The following code produces two different results if you comment out the "my" statement that defines the variables. Why should it matter? What's going on that I'm not getting? Are there now two sets of each variable, even tho they have identical names? And most importantly, what is the scope of the new variables that are sprung into existence within the "foreach" loop that's doing the assignments? I want to "use strict" and am unsure of the implications. I want to make sure the variables that are used do not conflict with globals (from packages). Hence the desire to use "my". So, what gives?
my $n = 0; my ($zero, $one, $two, $three ); #### This is the "my" in question foreach ( qw( zero one two three ) ) { $$_ = $n++ || "zero"; } my $msg = ""; foreach ( qw( zero one two three ) ) { $msg .= "$_ = '$$_'\n"; } print $msg; print qq( zero = '$zero' one = '$one' two = '$two' three = '$three' );

Replies are listed 'Best First'.
Re: when is "my" not necessary?
by runrig (Abbot) on Nov 02, 2004 at 20:00 UTC
    my creates lexical variables. When you use symbolic references (as in your foreach loop), you are referring to package variables. If you print $main::zero, etc. you will see the results of your assignments. Note that symbolic references are usually a bad thing, and you should almost always use strict.

    Update: Some relevant reading material.

      And when you *do* start using strict, it won't let you use symbolic (soft) references anyway.
      OK.. This is driving me crazy. In package x, I have @list = ('a','b','c'). In package y, (after requiring package x), I try: my($a,$b,$c)=(); $a = 'Here'; $b = 'Present': $c = 'Me too'; for(@x::list){ if ($$_) {print "$_ has a value"} } but this does not work using 'my'. I too have moved to stict to support mod_perl (what an excercise!). Why do I do this? I collect form variables (stored in $a,$b,$c) but if they are in @a::list (or better yet, a comma separated database column), they are user-required (and display an error to user if missing). Is this a bad use for symbolic references? What would you do?
        Storing form variables in global variables feels like a very bad idea to me, for the same reason any unrestricted set of global variables is a bad idea.

        Personally I prefer a hash to store the form variables in, CGI.pm does support it, though its a rather new feature, and it's rather well hidden. Look up the method Vars.

Re: when is "my" not necessary?
by hardburn (Abbot) on Nov 02, 2004 at 20:13 UTC

    In addition to what runig said, note that Perl has two places to store variables. The first is the lexical scope pad. That's where my variables go. Lexical scopes can be created and destroyed by a lot of things, but the most common is within blocks:

    my $n = 1; { my $n = 2; print $n; # Prints 2 } print $n; # Prints 1

    The second place is the symbol table. This is where variables declared our and local go (among other things). The symbol table can be accessed directly from Perl code (you need a C-based backend to play with the lexical pad directly).

    Using lexicals is usually the Right Thing.

    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

      Lexical scopes can be created and destroyed by a lot of things

      Out of interest, what else can destroy them?

        A package statement. The end of a string eval. Probably a bunch of other stuff I can't remember ATM.

        "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

Re: when is "my" not necessary?
by revdiablo (Prior) on Nov 02, 2004 at 20:54 UTC

    Since it has been suggested that you use strict and avoid symbolic references, the inevitable question will be "then how do I do what I'm trying to do here?" The answer is almost always to use a hash. Here's a quick example of your code ported to use a lexically scoped hash:

    my $n = 0; my %nums; foreach ( qw( zero one two three ) ) { $nums{$_} = $n++ || "zero"; } my $msg = ""; foreach ( qw( zero one two three ) ) { $msg .= "$_ = '$nums{$_}'\n"; } print $msg; print qq( zero = '$nums{zero}' one = '$nums{one}' two = '$nums{two}' three = '$nums{three}' );

    You get the benefit of being able to dynamically create entries in the hash, without the side-effect of possibly clobbering unrelated variables.

      thanks for everyone's reply. So my two main questions now are:

      Just why are lexicals "the right thing?" Both clearly have their uses and their purposes (and scopes), but is it really that one is "the right thing?", or is it just the you have to use the appropriate method at the appropriate time?

      The second question is, what is the advantage of using this form of hash:

      my $hash; $hash{foo} = bar;
      vs. this form of hash:
      my $hash = {}; $hash->{foo} = bar;
        Just why are lexicals "the right thing?"

        Unless you are very careful to use local, package variables (the kind you get when you don't use my) are always global. Even when you do use local, there are many surprises waiting in store. Package variables make action at a distance far too easy.

        Lexical variables, on the other hand, are usually very safe. You know that when you scope a lexical variable to a specific block, nothing outside of that block can access it. You also know that you are not clobbering any other variables of the same name from other scopes. It's just the right way to go 99.95% of the time. The whole history of computer science has proved this out -- people are constantly thinking of new ways to keep pieces of code from inadvertantly interacting with and breaking other pieces of code.

        The second question is, what is the advantage of using this form of hash . . . vs. this form of hash

        The first one you showed was a hash, the second was a hash reference. References are very useful for a variety of reasons, but unless you actually need one, I advise sticking with a plain hash. I have no objective reasons, other than reducing the amount of unnecessary syntax (which, especially when writing Perl code, is always something to strive for).

        my $hash; $hash{foo} = bar;
        Once again, you are not using strict (and you have two different variables named 'hash'). The first line above refers to the lexical scalar variable $hash (which in your second example you use as a hash reference, which is just another type of scalar); the second line, assuming there is nothing else in this program, is referring to the package variable %main::hash. If you wanted to make a lexical hash you would go:
        my %hash; $hash{foo} = 'bar';
        You should use strict, as your second line also uses the bare word 'bar', which gets interpreted as a string, but is a dangerous thing to rely upon, and won't work under strict anyway (and assigining to the undeclared hash is also not allowed under strict). Maybe a look through perldata is in order.
        Only lexicals have scope which is why they're "the right thing". You can learn all this and more by reading perldata. RTFM.

        Well...

        my $hash; $hash{foo} = bar;
      • Creates a lexical scalar named $hash
      • Assigns 'bar' to the key 'foo' in the global variable %hash (or, more accurately, %main::hash)

        If you meant:

        my %hash; $hash{foo} = 'bar'; #Versus my $hash = {}; $hash->{foo} = 'bar';

        Then there is still a difference. In the first, you create a lexical hash named %hash, then assign a value to one of it's keys. In the second you create a lexical scalar which contains an anonymous reference to a hash.

        To examine the difference, run this:

        #!/usr/bin/perl use strict; use warnings; use Data::Dumper; print "A lexical hash:\n"; my %hash; $hash{foo} = 'bar'; print Dumper(\%hash); print "A lexical hash *reference*:\n"; my $hash = {}; $hash->{foo} = 'bar'; print Dumper(\$hash);
        Note how the variable in the second case "points to" (is a reference to) the actual hash, while the first case is just the hash. I highly suggest reading up on references, and man perlvar -- the nuances are important and often incredibly useful. ;-)

        radiantmatrix
        require General::Disclaimer;
        "Users are evil. All users are evil. Do not trust them. Perl specifically offers the -T switch because it knows users are evil." - japhy
Re: when is "my" not necessary?
by Anonymous Monk on Nov 03, 2004 at 17:09 UTC
    This happens because when you do
    $$_ = foo ;
    you are setting to a GLOBAL variable, not lexical (defined by my). So if $_ is equal 'zero' you are setting:
    $main::zero = foo ;
    To really set a lexical variable you should use eval:
    eval("\$$_ = foo") ;
    Note that when you write
    my $zero ; ... print "$zero" ;
    the $zero variable inside the string to be printed will point to a lexical variable, and all the symbolic references are evaluated at runtime and will point to the package (symbol table), in other words, will point to a global variable.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2024-04-24 15:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found