Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

declare variable in loop with Perl

I am fairly new to Perl and have recently produced the following piece of code. I have tested it extensively and it returns the desired results. However I just wondered if someone with more experience of Perl could advice me on its usability.

Basically, I have declared an array variable with the 'my' keyword inside a for loop. I then use the address of this declared array variable in another array variable that has been declared before the aforementioned for loop. The basic code structure looks like this:

my @Array_of_ALL_Vals;
for my $iloop (0 .. 10){
    my @Array_Vals;
    .
    Code in here to populate @Array_of_Vals
    .
    push @Array_of_ALL_Vals,\@Array_Vals;
}

The @Array_Vals variable is, in general, a different size each time. In addition the array @Array_Vals defined inside the loop is not used anywhere else in the code and is local to the for loop.

My concern is with the declaration of the array within the for loop. Even though the name of the variable is the same each time I assume that for each loop iteration it gets assigned to a different memory address. Is this correct?

I thought it would be better to add an incrementer to the array name inside the for loop so the name would be different each time (@Array_Vals1,@Array_Vals2,...). Then I could push these values into the @Array_of_ALL_Vals array and be sure that the final arrays values would not be overwritten. However after doing some searches I found that such methods are discouraged (variable name containing variable).

So I suppose what I am asking is: Is my method of using the same array name for each loop iteration and then appending the address of this array to a new array (@Array_of_ALL_Vals) valid? Or, does the fact that the loop array (@Array_Vals) keeps getting overwritten mess up the validity of my array @Array_of_ALL_Vals (which contains the addresses of the @Array_Vals array) after all iterations have been performed?

Many thanks for any comments

Gauss76

like image 817
gauss76 Avatar asked Aug 08 '17 09:08

gauss76


1 Answers

Each time you enter your loop, you get a brand new variable called @Array_Vals. Each of these variables will live in a different part of memory and will, therefore, have a different reference. You can verify this by printing the reference to your array (print \@Array_Vals) inside your loop.

So you have a new array variable, which you then populate. And then you take a reference to that array and store the reference in another array. We're then at the end of the loop iteration and @Array_Vals goes out of scope and ceases to exist. Or, rather, the name of the variable ceases to exist. When we stored a reference to @Array_Vals in @Array_of_All_Vals, Perl internally made a note that this reference was being stored elsewhere (we say "the reference count was incremented"). And while the reference count is non-zero, Perl will not free up the memory that was used to store the old @Array_Vals array.

If the @Array_of_All_Vals array was to ever go out of scope, then Perl would decrement the reference count on all of the references stored in its elements. The reference count on the old @Array_Vals array would go to zero and Perl's garbage collection would be free to re-use that memory at some point in the future.

So, the mechanism you've developed is guaranteed to work fine. In fact it's the recommended approach to situations like this.

like image 91
Dave Cross Avatar answered Sep 18 '22 06:09

Dave Cross