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

I have seen discussion on cloning array, deep copies etc.
I'm trying to do some "Elegant" coding, so I'd like to understand how to do the equivalent of the following : my @localarray = @{$PassedArrayRef}; I'm not sure if this does what I expect, efficiently. What I would like to have that do is to convert the array reference into an array, so I can avoid ugly syntax like $$PassedArrayRef[$index], and use $localarray[$index] instead.

However, I don't want to pay the penalty of member-wise cloning of the array.

Thoughts, and wisdom appreciated.

Edit: Added <code> tags. larsen

Replies are listed 'Best First'.
Re: Converting an Array Reference into an Array
by chromatic (Archbishop) on Mar 12, 2003 at 07:50 UTC

    Under the hood, an array reference and an array are the same thing. (There are just two hoods to look under with an array reference.) Your technique for turning an array reference into an array is workable and the proper way to do it, but you are paying the penalty of cloning the array because you're copying things.

    There's really no good way to do what you're suggesting without cloning things, unless you want to be very sneaky and mess with typeglobs. I prefer this dereferencing syntax, though:

    my $element = $PassedArrayRef->[ $index ];

    Just for kicks, here's the typeglob/global syntax you really oughtn't use. (If you don't understand it, you're probably better off!)

    local *notacopy; *notacopy = $PassedArrayRef; my $element = $notacopy[ $index ];

    I can't think of a good reason to do that, though.

      Thanks for those insights. I just discovered a relevant discussion on what I was trying to understand - a reference to an array of arrays.

      I have discovered that the documentation in the "perllol manpage" is pretty good for this subject.

      Also, I consider the syntax of $ArrayRef->[$index] to meet my "Elegance" standards (Better than $$ArrayRef[$index]). The glob stuff seems cool too, but, without a full understanding of the implications, I'll treat it as dangerous and eschewable.

      Thanks for bestowing all the wisdom, and cleaning up my message format. (I'm still learning, and hope to do that for the rest of my life).

Re: Converting an Array Reference into an Array
by PodMaster (Abbot) on Mar 12, 2003 at 07:54 UTC
    perl -e" $a=[1]; *a = $a; warn @a;die $a[0]"
    SEE ALSO perldata,perlref


    MJD says you can't just make shit up and expect the computer to know what you mean, retardo!
    I run a Win32 PPM repository for perl 5.6x+5.8x. I take requests.
    ** The Third rule of perl club is a statement of fact: pod is sexy.

Re: Converting an Array Reference into an Array
by robartes (Priest) on Mar 12, 2003 at 07:51 UTC
    A quick look with B::Terse (hey, I learned a new trick, I'm gonna use it :) ) at this:
    my $aryref=[ qw(one two) ]; my @array=@$aryref; my @arraytwo=qw(one two);
    Shows this as a result:
    LISTOP (0x8115698) leave [1] OP (0x8120b78) enter COP (0x8115658) nextstate BINOP (0x8115630) sassign UNOP (0x81795e0) srefgen UNOP (0x8120cd8) null [141] LISTOP (0x8120340) anonlist OP (0x8120cb8) pushmark SVOP (0x811a068) const PV (0x811d8e4) "one" SVOP (0x81203c0) const PV (0x811d8d8) "two" OP (0x814db90) padsv [1] COP (0x81157d0) nextstate BINOP (0x8115770) aassign [4] UNOP (0x8115728) null [141] OP (0x8115750) pushmark UNOP (0x81156c0) rv2av [3] OP (0x8179600) padsv [1] UNOP (0x81156e0) null [141] OP (0x8115708) pushmark OP (0x81795c0) padav [2] COP (0x8120b38) nextstate BINOP (0x8120b10) aassign [6] UNOP (0x8120a80) null [141] OP (0x8120aa8) pushmark SVOP (0x8120a40) const PV (0x811d908) "one" SVOP (0x8120a60) const PV (0x811d8f0) "two" UNOP (0x8120ac8) null [141] OP (0x8120af0) pushmark OP (0x8115810) padav [5] cloning.pl syntax OK
    In other words, the @array=@$aryref does not copy the array members, it just sets up @array to point to the data pointed to by $aryref (and increases said data's refcount). Perl does the right thing here. So, you should not expect a performance penalty for this. You should still have some penalty (notably, pointing the new array's members to the SV's), but not the same as creating a full blown array from the ground up. Ah well, rv2av is apparently a full blown copy. Never mind my blabbering. Thanks chromatic and PodMaster.

    However, I would try and get used to the 'ugly syntax' of references and dereferencing them - they are among the most powerful features of Perl and are the only way of building complex data structures. You will need them :)

    Update: Stopped lying. :)

    CU
    Robartes-

      This is incorrect. rv2av dereferences an array reference. Search for pp_rv2av in pp_hot.c.

      That is not accurate.
      my $coy = [ 1, 2]; my @coy = @$coy; $coy[1] = 666; use Data::Dumper; die Dumper( $coy, \@coy ); __END__ $VAR1 = [ 1, 2 ]; $VAR2 = [ 1, 666 ];
      Don't ask me to explain, I don't know Terse (and may be some "copy on write" magic going on).


      MJD says you can't just make shit up and expect the computer to know what you mean, retardo!
      I run a Win32 PPM repository for perl 5.6x+5.8x. I take requests.
      ** The Third rule of perl club is a statement of fact: pod is sexy.