in reply to Re^3: Negative array subscript method call bug?
in thread Negative array subscript method call bug?

How about just "method called on undefined value"?

perl -e'$x= $x[-1]' $x is, of course, undefined.

So logically $x=$x[-1];$x->meth and $x[-1]->meth should produce the same error, right? Theres no attempt at creation anywhere. Just trying to find an index that doesn't exist.

 $x[1]->meth produces the "Can't call method on undefined value" error, so why is -1 different than 1 when neither exist?

Replies are listed 'Best First'.
Re^5: Negative array subscript method call bug?
by BrowserUk (Patriarch) on Aug 08, 2004 at 07:27 UTC

    It's a case of which error came first.

    In this first case, $x[ 0 ] exists, so $x[ -1 ] can be translated as

    $x[ @x - 1 ] ==> $x[ 1 - 1 ] ==> $x[ 0 ]

    which is valid and currently undef, so the error occurs when try to indirect through undef for the method call.

    P:\test>perl -e" @x = undef; $x[ -1 ]->fred()" Can't call method "fred" on an undefined value at -e line 1.

    But in this case you have $x[ 0 - 1 ], which translates to a post-normalisetion, negative index (-1), which is illegal.

    So that's the error you see, and the indirection is never attempted.

    P:\test>perl -e" $x[ -1 ]->fred()" Modification of non-creatable array value attempted, subscript -1 at - +e line 1.

    Of course, the subscript normalisation also incorporates $[, but the always 0...right :)

      In this first case, $x[ 0 ] exists, so $x[ -1 ] can be translated as
      Which first case? In all of my cases, @x is empty. my @x; @x = (); $x = $x[-1]; $x->meth Theres no problem there with just *accessing* the non existant index to assign it to a variable. It doesn't even error. So why does calling the method attempt to modify it and there for create aforesaid error message?

        So what do you expect it do instead? Do you want it to be such that

        $x->[-1]=$y; # is the same as $x->[0]=$y; # when @$x==0 ?

        ---
        demerphq

          First they ignore you, then they laugh at you, then they fight you, then you win.
          -- Gandhi


        I've eventually arrived at the conclusion that there is a bug here.

        With my @x = (); my $x = $x[-1];

        You don't get the "Modification of non-creatable array value attempted, subscript -1 ... " error, because when Perl attempts to normalise the subscript, it calls FETCHSIZE on the array to find the upper limit from which it will then subtract the negative index to find the actual index.

        When the array is empty, FETCHSIZE returns 0, it therefore assumes that it can forgo autovivification of the array element as it will be initialised to undef anyway (and may never be used again), and just sets $x = undef;.

        This is a bug because if @x were a tied array, then there is no guarentee that the attempt to FETCH the value of a currently non-existant array element wouldn't autovivify a value other than undef.

        However, I think that this is already a known bug for tied arrays: (from Perl5.8.0 delta)

        Tied/Magical Array/Hash Elements Do Not Autovivify For normal arrays $foo = \$bar[1] will assign undef to $bar[1] (assumi +ng that it didn't exist before), but for tied/magical arrays and hash +es such autovivification does not happen because there is currently n +o way to catch the reference creation. The same problem affects slici +ng over non-existent indices/keys of a tied/magical array/hash.

        With my @x = (); $x[ -1 ]->meth;, Perl knows it needs a reference to the array element (not just it's value), and therefore tries to autovivify the element. At that point, it does the normalisation of the index, which results in a normalised negative index, which is illegal, and issues the error message.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
      A reply falls below the community's threshold of quality. You may see it by logging in.