Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Does @{ } copy arrays?

by tford (Beadle)
on Oct 16, 2009 at 19:32 UTC ( #801632=perlquestion: print w/ replies, xml ) Need Help??
tford has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to write Perl code that checks whether a given portion of a data structure (an array) has elements in it, or not.

It will need to perform this check many many times, so I'm worried about efficiency.

What I'm thinking about writing is

if( @{ $complete->{landmarks}->{LOG}->[$i][$j][$p] } ) { # return early, there's nothing to do here }

The $complete->{landmarks}->{LOG}->[$i][$j][$p] element has to be an array reference (right ?) so I want to test if the array pointed to by that actually holds stuff or not.

What I would hope is that the array is just examined "in place" and it already has some field that records how many elements it contains. Then the check could be performed very quickly. However, for some reason I have the idea that it would copy the whole array to an anonymous location first, and then return the number of elements it copied. Is this even close to the truth?

If so is there a more efficient way to do it?

Thanks in advance,

~tford

Comment on Does @{ } copy arrays?
Select or Download Code
Re: Does @{ } copy arrays?
by bv (Friar) on Oct 16, 2009 at 20:06 UTC

    Something I figured out recently is that you can dereference an array ref with $#{} to get the index of the last element. An empty array has it's "last element" at -1, so try this:

    if ( $#{ $complete->{landmarks}->{LOG}->[$i][$j][$p] } >= 0 ) { #Whatever }

    Update: While that will fix your issue, it doesn't answer the question you asked in the subject. Hopefully someone can answer that authoritatively, but I'll go out on a limb and say that dereferencing shouldn't make a copy of the array. It should tell the interpreter, "There is an array at the end of this pointer." Then the interpreter says, "Thanks, I'll just use that in scalar context now", which should be just fine.


    print pack("A25",pack("V*",map{1919242272+$_}(34481450,-49737472,6228,0,-285028276,6979,-1380265972)))
      Please don't use $#{..} >= 0. As well as being uglier and more long winded than @{...}, it's less efficient in perl 5.10.0 onwards (attaching of PERL_MAGIC_arylen magic to the AV).

      Dave.

        less efficient in perl 5.10.0 onwards (attaching of PERL_MAGIC_arylen magic to the AV).

        Is that going to revert?


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        Well, wouldn't $#{}, and @{} in a scalar context need similar magic? Isn't the second just an increment of the first? (There must be more magic anticipated by $#{} to warrant the slowdown?)

        -QM
        --
        Quantum Mechanics: The dreams stuff is made of

        Interesting! That's the kind of answer I was hoping someone would post. For anyone who's keeping score, here's a benchmark and my results:

        #!/usr/bin/perl use strict; use warnings; use Benchmark qw(cmpthese); my $i=0; cmpthese(-10, { deref => sub { my $aryptr = [qw(Once upon a time in a galaxy far far away +)]; if ( @{ $aryptr } ) { $i=1; } $aryptr = []; if ( @{ $aryptr } ) { $i=-1; } }, arylen => sub { my $aryptr = [qw(Once upon a time in a galaxy far far away +)]; if ( $#{ $aryptr } >= 0 ) { $i=1; } $aryptr = []; if ( $#{ $aryptr } >= 0 ) { $i=-1; } }, } ); __END__ Rate arylen deref arylen 95903/s -- -28% deref 132418/s 38% --

        print pack("A25",pack("V*",map{1919242272+$_}(34481450,-49737472,6228,0,-285028276,6979,-1380265972)))
        Uh oh, please don't tell people this, they'll think perl is stupid
Re: Does @{ } copy arrays?
by jwkrahn (Monsignor) on Oct 16, 2009 at 20:08 UTC

    The code you posted does not copy anything, it just dereferences an array reference.    It is the same as using an array in scalar context.

Re: Does @{ } copy arrays?
by lamprecht (Friar) on Oct 16, 2009 at 20:10 UTC
    Hi,

    perl seems to be 'clever' enough not to copy that array. (Maybe depending on the version: Tested with 5.8.8)


    Cheers, Christoph
Re: Does @{ } copy arrays?
by Anonymous Monk on Oct 16, 2009 at 22:49 UTC

    @{} in scalar context returns the number of elements in the array. Neither the array or its elements are copied.

    if (@{...}) { print("Not empty\n"); } else { print("Empty\n"); }

    - ikegami

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://801632]
Approved by toolic
Front-paged by SuicideJunkie
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (7)
As of 2014-09-19 09:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (133 votes), past polls