Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying array in subroutine

Tags:

perl

I've got some code that doesn't work the way I expect, and I'd appreciate some help figuring out how to get it working the way I DO expect.

I'd like to use a subroutine to modify an input array. I figured that if I passed in a reference to the array, any changes I made to it would be reflected in the caller's version, too. But it apparently doesn't work that way.


my @test_array = qw (zero one two three);

shift_array(\@test_array);
print "POST SUBROUTINE: $test_array[0]\n";

sub shift_array {
    my @array = @{(shift)};
    shift @array;
    print "AFTER SHIFT IN SUB: $array[0]\n";
}

This prints:

AFTER SHIFT IN SUB: one
POST SUBROUTINE: zero

I expected it to print one both times.

So my question is two-fold:

1) Why isn't it behaving the way I think it should? Does passing a reference to an array create a copy of the array?

2) How do I get the behavior I WAS expecting? How do I I get a subroutine to slide one or more elements off of the front of caller's copy of an input array?

Thanks in advance for any insight you can offer.

like image 754
BlairHippo Avatar asked Apr 03 '12 14:04

BlairHippo


People also ask

How to change array within function?

We can change the contents of array in the caller function (i.e. test_change()) through callee function (i.e. change) by passing the the value of array to the function (i.e. int *array). This modification can be effective in the caller function without any return statement.


2 Answers

Because my @array is a new array that you assigned the dereferenced original array to. It's a copy.

Instead do this:

sub shift_array {
    my $array = shift;
    shift( @$array );
}

Edit: I originally said dereferencing it creates the problem but using @$array is still dereferencing it. As @mob pointed out, assigning the variable is what creates the new array instead of updating the existing reference.

like image 109
Cfreak Avatar answered Dec 08 '22 15:12

Cfreak


This is one of the (tiny number) of cases where Perl prototypes are useful.

#!/usr/bin/perl

use strict;
use warnings;

# Prototype forces the first argument to be a reference to an array    
sub shift_array (\@) {
  my $array = shift;
  shift(@$array);
  print "AFTER SHIFT IN SUB: @$array[0]\n";
}

my @test_array = qw (zero one two three);

shift_array(@test_array);
print "POST SUBROUTINE: $test_array[0]\n";
like image 42
Dave Cross Avatar answered Dec 08 '22 16:12

Dave Cross