Search code examples
arraysfunctionperlsubroutinedereference

Perl: How do you dereference an array without creating a copy of the array?


When I dereference an array using @$arrayRef or @{$arrayRef} it appears to create a copy of the array. Is there a correct way to dereference an array?

This code...

sub updateArray1 {
        my $aRef = shift;
        my @a = @$aRef;
        my $aRef2 = \@a;

        $a[0] = 0;
        push(@a, 3);
        my $aRef3 = \@a;

        print "inside1 \@a: @a\n";
        print "inside1 \$aRef: $aRef\n";
        print "inside1 \$aRef2: $aRef2\n";
        print "inside1 \$aRef3: $aRef3\n\n";
}

my @array = (1, 2);

print "before: @array\n";
my $ar = \@array;
print "before: $ar\n\n";

updateArray1(\@array);

print "after: @array\n";
$ar = \@array;
print "after: $ar\n\n";

... has the output...

before: 1 2
before: ARRAY(0x1601440)

inside1 @a: 0 2 3
inside1 $aRef: ARRAY(0x1601440)
inside1 $aRef2: ARRAY(0x30c1f08)
inside1 $aRef3: ARRAY(0x30c1f08)

after: 1 2
after: ARRAY(0x1601440)

As you can see, @$aRef creates a new pointer address.

The only way I've found to get around this is to only use the reference:

sub updateArray2 {
        my $aRef = shift;

        @$aRef[0] = 0;
        push(@$aRef, 3);

        print "inside2 \@\$aRef: @$aRef\n";
        print "inside2 \$aRef: $aRef\n\n";
}

updateArray2(\@array);

print "after2: @array\n";
$ar = \@array;
print "after2: $ar\n\n";

Which produces the output:

inside2 @$aRef: 0 2 3
inside2 $aRef: ARRAY(0x1601440)

after2: 0 2 3
after2: ARRAY(0x1601440)

Is it possible to dereference a pointer to an array without the whole array getting duplicated? Or do I need to keep it in reference form and dereference it any time I want to use it?


Solution

  • Dereferencing does not create a copy as can be seen in the following example:

    my @a = qw(a b c);
    my $ra = \@a;
    @{$ra}[0,1] = qw(foo bar);  # dereferencing is done here but not copying
    print @$ra; # foo bar c
    print @a; # foo bar c
    

    Instead, assigning the (dereferenced) array to another array creates the copy:

    my @a = qw(a b c);
    my $ra = \@a;
    my @newa = @$ra;   # copy by assigning
    $newa[0] = 'foo';
    print @newa; # foo b c
    print @a; # a b c
    

    Assigning one array to another says essentially that all elements from the old array should be assigned to the new array too - which is different from just having a different name for the original array. But assigning one array reference to another just makes the old array available with a different name, i.e. copy array reference vs. copy array content.

    Note that this seems to be different to languages like Python or Java because in these languages variables describe array objects only, i.e. the reference to the array and not the content of the array.