in reply to Re: declaration of variables
in thread declaration of variables

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.

Replies are listed 'Best First'.
3Re: declaration of variables
by jeffa (Bishop) on Sep 02, 2003 at 15:32 UTC
    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
Re: Re: Re: declaration of variables
by davido (Cardinal) on Sep 02, 2003 at 17:01 UTC
    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

Re: Re: Re: declaration of variables
by tilly (Archbishop) on Sep 03, 2003 at 04:56 UTC
    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.