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

>perl -e"$x[-1]->meth" Modification of non-creatable array value attempted, subscript -1 at - +e line 1.
Opposed to:
>perl -e"undef->meth" Can't call method "meth" on an undefined value at -e line 1.
Opinions?

Update:
After further experimentation and consultation with "Somni" on irc, the problem is the attempted autovivification. The same error occurs with $x[-1]="foo" when @x has no elements. If theres no element, there can not be a last element. That makes a certain amount of sense but the error message is a tad misleading.

Replies are listed 'Best First'.
Re: Negative array subscript method call bug?
by shemp (Deacon) on Aug 07, 2004 at 02:02 UTC
    This happens when the array has no elements. index -1 means the last array element, and when the array is empty, the last element is not element 0, its undefined. I asked the exact same question a while ago, theres a thread that i originated. If i feel so motivated later, i'll dig it up, otherwise check out my profile. Merlyn gave a wonderful explanation. Heres code to deal with your situation:
    if ( @x ) { $x[-1]->meth(); } else { die "no elements in \@x\n"; # r whatever }
    Heres the thread: array index -1 oddity
Re: Negative array subscript method call bug?
by davido (Cardinal) on Aug 07, 2004 at 04:38 UTC

    Try this one for size:

    perl -e '$x[-1] = 0;' __OUTPUT__ Modification of non-creatable array value attempted, subscript -1 at - +e line 1.

    It would appear that you cannot autovivify an array element by counting backward from the last element using negative subscripts. Likewise, this will throw the same error:

    perl -e '@x = ( 1, 2, 3 ); $x[-4] = 0;'

    Again, this is attempting to autovivify an element prior to the first element ($x[0]) by using a negative index that will count backward past the beginning of the array.

    I don't consider the fact that you can't do this to be a bug, if ever there were a feature, this is it. ;)

    Update: After reading your update, I just wanted to comment: I really think that the problem is two-fold: First, you're attempting to autovivify by indexing backwards from an array that has no elements (so there is no concept of the last element). The second problem is that even if the array has elements (thus creating a concept of 'last element'), attempting to index to the left of the first element (ie, before $x[0]) is another impossibility; you can't autovivify an element prior to the first element of an array. In an array that contains no elements, you're breaking both rules; you're attempting to count backward from the last element, when there is no last element. And since there is no last element, any element you autovivify by counting backwards will have to come before the nonexistant first element. It's madness.


    Dave

      Addressing your update: Right, I got most of that on my own and thats basically what I was attempting to convery in my update. Now I just think the error message sucks =]
Re: Negative array subscript method call bug?
by hossman (Prior) on Aug 07, 2004 at 17:34 UTC

    As a general rule, perl error messages try to be as short as possible while still conveying all of the neccessary info that sets *this* type of error apart from *that* type of error.

    The main motivation for this (as i understand it) is to keep them short for people who allready understand the various classes of problems, and just need a quick pointer to the line number and the type of think they screwed up.

    If/when people are confused by perl error messages, they should ALWAYS consult perldiag, or use diagnostics

    laptop:~> perl -Mdiagnostics -e 'my @x; $x[-1]->meth' Modification of non-creatable array value attempted, subscript -1 at - +e line 1 (#1) (F) You tried to make an array value spring into existence, and th +e subscript was probably negative, even counting from end of the arr +ay backwards. Uncaught exception from user code: Modification of non-creatable array value attempted, subscript + -1 at -e line 1.
      Yes, buy why does doing ->meth involve a modification or a creation of the left hand side?

        I started to write this...

        It doesn't. perl can't even make it that far because it can't figure out what it is you are trying to call "meth" on. Before it ever even gets arround to trying, it has to "make an array value spring into existence" and when it tried, it found that "subscript -1" ment "the subscript was (probably) negative" so ultimately you were asking it to set (aka: modify) a "non-creatable array value"

        ...but then i started to see your point: "Modification" ? why is refrencing the (non-creatable) array value to call a method on it considered a modification?

        It would make more sense to say something like "Reference of non-creatable array value attempted"...

        laptop:~> perl -e '$y = \$x[-1000];' Modification of non-creatable array value attempted, subscript -1000 a +t -e line 1.