in reply to declaration of variables

or what is the best way to declare a variable?

I'll respond to that question first. The best way depends on what you're trying to accomplish, and the 'scope' you're trying to achieve.

my declares variables to exist within the innermost block. In this sense, I mean block as a literal { } pair, or as a subroutine, or as a file, or even as an eval. What this means is that when you declare a variable with my, it lives within the block in which it was declared, and falls out of scope when the block itself passes from scope. It probably gets a little more complicated than that sometimes (if you make it), but generally just count on variables declared with 'my' as existing within the block in which they were declared. But that probably wasn't really your question.

You were asking what is the difference between some of the commonly seen usages of 'my'. I'll try to respond accurately. I'm sure if I miss something we'll hear about it. ;)

my $var; # Declares a single variable.

The following example assigns the variable a value:

my $var = "Hello world!\n"; my $var = 10; my $var = 0; my $var = ""; my $var = \@some_array; my $var = \%some_hash; my $var = \$some_scalar; my $var = \&some_function;

In the preceeding examples, you're assigning $var some value. It is not always necessary to assign $var the value of "" (the null string). Unlike C, variables in Perl are already empty when you create them. But empty in this case means undefined. In the context of "What is false" and "What is true", undef, "" (null string), and 0, are all "false". But if you are counting on a null string, assign it as in your examples. Redundancy isn't always bad either; in some cases you'll want to assign something, even if it's nothing, to add clarity.

What if you want to declare multiple variables? my binds more tightly than the comma, so you cannot just say, my $this, $that;. You must use paranthesis:

my ( $this, $that );

The parenthesis are also serving the dual function of (1) Specifying order of precedence so that the comma binds more closely than the my. And (2) the parenthesis have also created a list. That means you can legitimately do this:

my ( $this, $that ) = ( "the", "other" );

It is not wrong to say,

my ($var);

or

my ($var) = "This";

It's just not *necessary* in this situation to use the parens. ...but it doesn't hurt anything.

Some additional things you can do:

my ( $this, $that ) = "The other";

Now $this has been assigned a value, and $that has not. ...and you can do this:

my @array = ("This", "That", "and", "The", "Other"); my %hash = ( "This" => "That", "The" => "Other" ); my $var = ("This", "That"); # $var now contains "That". my ( $this, $that ) = \( $the, $other ); # The reference # constructer is distributive and # applies to both items inside the rvalue # list.

And there are plenty of other things you can do. Just remember, if there is more than one variable on the left, use parenthesis so that 'my' binds to both. The rest you'll find behaves pretty much how you expect it to when you need it.

Dave

"If I had my life to do over again, I'd be a plumber." -- Albert Einstein

Replies are listed 'Best First'.
Re: Re: declaration of variables
by bradcathey (Prior) on Sep 02, 2003 at 14:55 UTC
    Dave, one point of clarification on this thread: how would you "clear" a variable that you are using over again and again, such as in a loop? See line 7:
    1: my $tempstring; 2: for $i (1...10) { 3: for $j (1...10) { 4: $tempstring .= $array[$j]; } 6: $final[$i] = $tempstring; 7: $tempstring = ""; }
    or would/could you use:
    7: my $tempstring;
    or
    7: undef $tempstring;
    or is that declaring it too many times? or is using undef has bad as I've read?

    Thanks, and I will acolyte for you anytime.
      I think this is a perfectly valid place to undefine a variable. You could also use my to redeclare the variable, but there is no need to declare the variable both inside the loop and outside:
      my @final; my @array = qw(foo bar baz); for (0..$#array) { my $temp; for my $j (0..$#array) { $temp .= $array[$j]; } push @final, $temp; }
      Remember, undef is not bad, you just have to know when it is a good choice:
      my $temp; for (0..$#array) { for my $j (0..$#array) { $temp .= $array[$j]; } push @final, $temp; undef $temp; }
      Here, it is perfectly fine because we are undefining a scalar. But, what happens if we push another array instead?
      for my $i (0..$#array) { my @temp = @array; push @final, \@temp; undef @temp; }
      This is a bad choice. Now @final contains three anonymous, empty array references. What happened? We copied the contents of @array, but after we pushed our temp array, we undefined it - hence, we 'erase' the data we just pushed. But, had we pushed a new anonymous array reference that contained our temp array, then it works:
      for my $i (0..$#array) { my @temp = @array; push @final, [@temp]; undef @temp; }

      jeffa

      L-LL-L--L-LL-L--L-LL-L--
      -R--R-RR-R--R-RR-R--R-RR
      B--B--B--B--B--B--B--B--
      H---H---H---H---H---H---
      (the triplet paradiddle with high-hat)
      
        Wow, that's quite a thorough answer. I'm glad to get a practical explanation of undef.

        Blessings, bradcathey
      If you wanted to let scoping clear the variable for you, you can do it like this:

      1: for $i (1..10) { 2: my $tempstring; 3: for $j (1..10) { 4: $tempstring .= $array[$j]; 5: } 6: $final[$i] = $tempstring; 7: }

      What that does, is that $tempstring is declared in the outter for block. Each time you iterate through the outter for block, $tempstring falls out of scope at the end of the block, and is re-introduced in the next iteration. Quite literally, even on the last iteration of the outter for block, once you leave the block behind, $tempstring is gone. I prefer this method because it ensures that temporary, or loop variables just disappear when I don't need them anymore.

      For that matter, if you no longer are going to be needing access to $i and $j, you can declare them with block scope as well:

      for my $i (1..10) {.......

      This will ensure that at the end of the looping those variables also disappear, rather than possibly clouding up some other portion of your code. This is the merit of scoping; limiting scope! That's a good thing. IMHO, variables should only exist within the relm of where they are needed.

      Dave

      "If I had my life to do over again, I'd be a plumber." -- Albert Einstein

      The best answer to your question is to reverse lines 1 and 2, then omit line 7.

      But red flag alert!

      Any time you find yourself doing a lot of accessing a function by index, you are opening yourself up for potential looping bugs (off by one, fencepost, etc). As a sign of that I note that you are initializing your array by index in a loop that starts from 1. But Perl's arrays count by offset - the first index is always 0!

      Generally you can get rid of that source of error by letting Perl take care of the array accessing logic for you. (For those who have their priorities backwards, it is also marginally faster.)

      my @final; for my $i (1..10) { my $temp_string = ""; for my $x (@array) { $temp_string .= $x; } push @final, $tempstring; }
      Additional note. Note the my declaration on the loop variables? That is because I use strict.pm unless I have very good reason not to. (Free typo check! Why wouldn't I want that?) Hence I don't fall into any habits (such as not declaring loop variables) which conflict with that.