in reply to Re^6: Does @{ } copy arrays?
in thread Does @{ } copy arrays?

an edge case

Do you consider your example the common case? Relative to all the readonly uses of $#{}. Eg. 0 .. $#a; there are myriad others.

dave_the_m suggested elsewhere that "$#{..} >= 0. As well as being uglier and more long winded than @{...},". Well, ditto scalar( @a ) - 1 versus $#a.

But as so often in these cases, discussion is not entertained.

On the basis of a very casual survey of code on my system and cpan, this "optimisation" is a space pessimisation if 9 cases out of 10 I looked at. In some cases, extremely.

I'd love to see the evidence justifying the addition of tens of words to any array that you reference $#, in order to save "1 pointers-worth of memory just to store NULL" on those you don't. And that's before you consider the peformance effects.


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.
RIP PCW It is as I've been saying!(Audio until 20090817)

Replies are listed 'Best First'.
Re^8: Does @{ } copy arrays?
by LanX (Saint) on Oct 19, 2009 at 13:37 UTC
    as dave already said This could probably be optimised when pp_av2arylen is called in rvalue context.

    but my example shows that your suggestion Could not the application of magic to an array, and all the penalties that go with it, be deferred until it is used in an lvalue context? would effect manipulate code at long distance.

    And yes of course I consider my example to pass $#a as an argument an extremely common case.

    Cheers Rolf

      I consider my example to pass $#a as an argument an extremely common case

      While I disagree about the commonness of passing $#a, there are options if it is deemed to be too slow.

      • $#a as an arg is an lvalue. Users can pass 0+$#a if they want the extra speed of an rvalue.

      • $#a as an arg is an rvalue. Users can use ${ \$#a } if they want an lvalue.

      • $#a as an arg is a delayed lvalue. I don't know if the mechanism can be extended to $#a, but hash element lookups are like this:

        $ perl -le'\$h{k}; print exists($h{k})?1:0' 1 $ perl -le'sub{ $x=$_[0] }->($h{k}); print exists($h{k})?1:0' 0 $ perl -le'sub{ $_[0]=$x }->($h{k}); print exists($h{k})?1:0' 1 $ perl -le'sub{ $x=$_[0] }->(@h{k}); print exists($h{k})?1:0' 1 $ perl -le'sub{ $_[0]=$x }->(@h{k}); print exists($h{k})?1:0' 1

        Unfortunately, none of those 'remedies' work:

        C:\test>p1 [0] Perl> use Devel::Size qw[ size total_size ];; [0] Perl> @a = 1 .. 10;; [0] Perl> print size( \@a ), ':', total_size( \@a );; 256 : 496 [0] Perl> print $#a;; 9 [0] Perl> print size( \@a ), ':', total_size( \@a );; 440 : 680 C:\test>p1 [0] Perl> use Devel::Size qw[ size total_size ];; [0] Perl> @a = 1 .. 10;; [0] Perl> print size( \@a ), ':', total_size( \@a );; 256 : 496 [0] Perl> $x = 0+$#a;; [0] Perl> print size( \@a ), ':', total_size( \@a );; 432 : 672 C:\test>p1 [0] Perl> use Devel::Size qw[ size total_size ];; [0] Perl> @a = 1 .. 10;; [0] Perl> print size( \@a ), ':', total_size( \@a );; 256 : 496 [0] Perl> $x = ${ \$#a };; [0] Perl> print size( \@a ), ':', total_size( \@a );; 432 : 672

        In every case, the mere mention of $#a has already caused the damage to be done. Trading 76-bytes per array to save 4-bytes per array does not make sense.


        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.
        Hmm ... as far as I understood dave, copying to an rvalue doesn't help, because the array has already been "prepared" for later modification without taking care about any rvalue context !(?)

        so calling with arg @a-1 is always the fastest alternative.

        Cheers Rolf

      And yes of course I consider my example to pass $#a as an argument an extremely common case.

      The validity of your example as a counter-argument relies not just upon passing $#a as an argument to a sub, but also on:

      1. Not assigning the arguments to named lexicals within the sub as is normal:
        sub ...{ my( ..., ... ) = @_; }
      2. And then, using the $_[...] alias as an lvalue.

      I bet you cannot find a single example of anyone doing this on cpan; or in any publically available piece of real code.

      Ergo, not a common case.


      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.
        sigh...

        Look a compiler must cover _all_ cases not only what you consider "common"...

        Cheers Rolf