0

I am new to Perl, and I cannot figure this out. I have two seemingly identical sets of code, but one subroutine updates the value while another does not. In the first set of code, my understanding is that the reference to an array is passed, then the value at which that reference is pointing is updated. Then when leaving the subroutine, the value has been changed. However, in the second one, I would expect the same thing to occur. It does update the array, but then it forgets about it after leaving the subroutine. Can someone please explain to me what is going on behind the scenes with the second set of code?

First Code Set:

#!/usr/bin/perl -w

use strict;

{
    my @array = (1, 2, 3);
    removeSecondElement(\@array);
    print @array;  #output: 13
    print("\n");
}

sub removeSecondElement{
    my ($arrayReference) = @_;
    splice(@$arrayReference, 1, 1);
    print @$arrayReference;  #output: 13
    print "\n";
}

Second Code Set:

#!/usr/bin/perl -w

use strict;

{
    my @array = (1, 2, 3);
    removeSecondElement(\@array);
    print @array;  #output: 123
    print("\n");
}

sub removeSecondElement{
    my ($arrayReference) = @_;
    my @array = @$arrayReference;
    splice(@array, 1, 1);
    print @array;  #output: 13
    print "\n";
}
Evorlor
  • 7,263
  • 17
  • 70
  • 141

1 Answers1

7

In the first example, you use the reference to get the array and then you modify that. There is only one array and you change it.

In the second example, you use the reference to get the array, then you copy the content of the array into a second array, then you modify the second array. There are two arrays and you never alter the original one.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Is there a way to make the second set of code behave the way I anticipated while keeping that assignment? Such as my @array = \@$arrayReference;? (Althought that won't work.) I am new to Perl if you cannot tell :-) – Evorlor Feb 04 '15 at 14:31
  • That is, is there a way to make @array in the subroutine point to the same array that $arrayReference points to? – Evorlor Feb 04 '15 at 14:39
  • You might be able to, but it's probably a bad idea. `our @alias;*alias = \@array;` might do something like that. That might be worth a different question if you really want to know how. http://www.perlmonks.org/?node_id=976523 – Sobrique Feb 04 '15 at 14:43
  • 5
    @Evorlor, Yes, there are two ways. 1) `our @alias; local *alias = $ref;` 2) `use Data::Alias; alias my @array = @$ref;`. But seriously, get used to using references. – ikegami Feb 04 '15 at 14:45
  • @ikegami does that use a plugin? It tells me Data/Alias.pm cannot be located for my `use Data::Alias;` line for way #2. – Evorlor Feb 04 '15 at 14:48
  • I don't know what you mean by plugin. `use Data::Alias;` loads module [Data::Alias](http://search.cpan.org/perldoc?Data::Alias). If sounds like you don't have the module installed. – ikegami Feb 04 '15 at 14:53
  • @ikegami awesome, thanks. ill look into it. and first way works great! thanks Quentin too! – Evorlor Feb 04 '15 at 14:55
  • 4
    @Evorlor: I'm glad you have a solution, but please heed the warnings not to use that. It is a pointless overhead to create an alias, and many people won't understand it. – Borodin Feb 04 '15 at 15:01
  • 4
    and the first way uses a global variable, something that you should avoid whenever possible. here, it is easy to just use the reference directly instead of making a copy. if you really can't do that, I'd use your second code as is, but add `@$arrayReference = @array; return;` at the end. (By the way, your subs are implicitly returning whatever print returns; you should always use an explicit return at the end of a sub, even - or especially - if it returns nothing.) – ysth Feb 04 '15 at 15:04
  • @Quentin ya Quentin! dont mess with things you dont understand! :-p (joking) – Evorlor Feb 04 '15 at 15:09