csarid has asked for the wisdom of the Perl Monks concerning the following question:

Hello All,
I am having a bit of trouble getting the following code to work. What I want to do is first reference an array to a variable and then use the new reference as input to a subroutine or function and then print each value as it iterates through the array.
use warnings; use strict; my @array= (1,2,3,4,5); my $arrayref=@array; my $size=@array; mysub($arrayref); sub mysub { my (@aref)=@_; for ( my $i=1; $i<=$size; $i++ ) { print "value of i is:$i \n"; print "Array Value:@aref[$i] \n"; } }

I have checked the FAQ and several other posts but just can't seem to get this to work.

Thanks!

Replies are listed 'Best First'.
Re: reference array and pass ref to sub
by almut (Canon) on Mar 06, 2009 at 21:39 UTC

    To take a reference, you need

    my $arrayref = \@array;

    and to dereference it, you write

    my @array = @$arrayref; # whole array # or my $elem = $arrayref->[0]; # individual element

    In other words, your code should look something like

    use warnings; use strict; my @array = (1,2,3,4,5); my $arrayref = \@array; mysub($arrayref); sub mysub { my ($aref) = @_; for my $i (0 .. $#$aref) { print "value of i is:$i \n"; print "Array Value:$aref->[$i] \n"; } }
      That worked perfect. Thanks for the help!
Re: reference array and pass ref to sub
by Marshall (Canon) on Mar 06, 2009 at 23:39 UTC
    A "C" 1D "array" could be called in Perl as a "list". But a Perl list is very different and much more powerful than a "C" 1-Dimensional array. Just one part of this is that there is no need to keep track of the size! There are many aspects of this which are beyond the scope of this post.

    Perl is also different in many other respects to other languages. A variable like @array can have a list context as well as a scalar context. If you had written my $array = @array, $array would have been the number of elements in the list @array. In Perl, each type of variable has its own namespace, so $list=@list is completely fine.

    To take a reference to a list, use: my listRef = \@list. This is "sort of" like an address of an array in C.

    In the below code, I send a reference to a list into a sub. @$listRef expands that reference back into the original list.

    One of the really magic things about Perl is that it is almost NEVER necessary to use something like: for ( my $i=1; $i<=$size; $i++ ). There are situations for this, but only perhaps once per 5K+ lines of Perl code - this is a rare duck! I did print an "index" in one situation below, but note that it is NOT the looping variable!

    #!/usr/bin/perl -w use strict; my @list= (1,2,3,4,5); printListRef(\@list); sub printListRef { my $listRef = shift; ########### easy way ######## print "easy way\n"; print "@$listRef\n"; ############################# #### another way (ugly)########### print "\nugly index stuff way\n"; my $i =0; foreach my $item (@$listRef) { print "list element[$i]=$item\n"; $i++; } ########## perl way for item per line ### print "\nperl way with one item per line\n"; print join("\n",@$listRef),"\n"; } ## it might not be apparent, but the __END__ ##line stopped the compilation. Another cool this about Perl. __END__ prints: easy way 1 2 3 4 5 ugly index stuff way list element[0]=1 list element[1]=2 list element[2]=3 list element[3]=4 list element[4]=5 perl way with one item per line 1 2 3 4 5

      As long as we're trying to get the terminology right, Perl has both lists and arrays. And they're different. And it's kind of annoying since their differences are fairly minor. I don't know of any other language that makes this distinction - that's not to say they don't, but I just don't remember one doing so.

      my @array = (1,2,3,4,5);
      Here, @array is an array, and (1,2,3,4,5) is a list (of five elements: the numbers 1 through 5). They are different. For example, it wouldn't really be a list without the parenthesis, it'd be five numbers with the comma operator in between, which would then evaluate to just the first one (due to the precedence of the comma operator). Of course, if it were "1..5" instead, then the parenthesis isn't needed. Or if it were in some other list context, such as print for 1,2,3,4,5, then the parenthesis still isn't required. Got that straight yet?

      Ok, another difference is in the way you can take a reference: if you try \1,2,3,4,5, that's just not going to do anything sensical. How about \(1,2,3,4,5)? Well, that does something really groovy, but it's not the same as [1,2,3,4,5] (which is what it'd look like if you did \@array when @array contains 1..5).

      Finally, a bigger difference is in what happens when you try to modify it:

      $_ *= 2 for 1,2,3,4,5; # doesn't work because you're modifying constan +ts. @a = (1,2,3,4,5); $_ *= 2 for @a; # modifies @a because @a has copies of the constants i +nstead of the constants themselves
      but that, too, isn't definitive, because $_ *= 2 for $x, $y, $z works just fine.

      Personally, I don't see the big deal. There are already plenty of rules here, and delineating between lists and arrays isn't really required for understanding the language (I was writing perl for a few years before joining this site and finding out here). Mostly, we care about lvalues and rvalues. Maybe it's my C/C++ background showing, but I think that's where we should be concentrating on the differences more than "array" vs "list".

        I think the distinction between a "C" 1D array and a Perl list is getting missed here. In "C" a 1D array is of fixed size. In "C" if we want to take say the 3rd item out of an array, we have to do something about that "missing 3rd place". If this this was 6 elements before, then we have to "shrink it" and that process is expensive. In Perl, we can just take the 3rd thing out and that's it!

        The most fundamental dynamic data structure in C, the linked list is not necessary in Perl! Its built into the language!

        The Perl terminology is very clear when it comes to multi-dimensional structures. In "C" if I asked for a picture of a 2-D array, you couldn't do it! Because you'd have to ask me more questions, like do you want a traditional 2D array or a more practical 2D matrix (which would be an array of pointer to array).

        Basically Perl removes one level of complication from complex structures. Since doubly linked "C" lists and hash table are built into the language, amazing things can happen!

Re: reference array and pass ref to sub
by smokemachine (Hermit) on Mar 07, 2009 at 00:42 UTC
    @a = (1 .. 10); func(\@a); sub func{ @b = @{ shift() }; for(@b){ print $_, $/; } }