On Thu Jan 26 11:48:14 2012, EDAVIS wrote:
Show quoted text> Variables::RequireNegativeIndices complains about $x[$#x-1] and
> suggests using a negative array index instead. But in fact $x[-2]
> does not have quite the same semantics. If the array has only a
> single element then $x[$#x-1] will give that element, but $x[-2]
> is undef.
>
> Similarly $x[@x-2] is *not* equivalent to $x[-2], as the long text
> for this policy claims.
>
> It is still true that using ($#x - something) in an array index is
> usually bad practice, and that some kind of expression using a
> negative index would be a better way to write it. But the current
> short and long messages give the impression that you can simply
> replace the troublesome expression with one using a negative offset.
>
> As a special case $x[$#x] and $x[@x-1] and $x[-1] are indeed
> equivalent. The policy can suggest changing those without caveats.
> If the array index is not one of these cases then it needs to give
> a more nuanced warning.
Okay, I'm not Conway or any of the other Perl demiurges. But to my mind
the real reason that things like $x[@x-2] should not be used is that the
semantics change based on whether the computed index is negative, and if
I were rewriting the long explanation that's what I would focus on,
rather than the special cases where the three different constructions
actually give the same thing all the time. Something like
=pod
Perl treats a negative array subscript as an offset from the end. Given
this, the preferred way to get the last element is C<$x[-1]>, not
C<$x[$#x]> or C<$x[@x-1]>, and the preferred way to get the next-to-last
is C<$x[-2]>, not C<$x[$#x-1> or C<$x[@x-2]>.
The biggest argument against the non-preferred forms is that their
semantics change when the computed index becomes negative. If C<@x>
contains at least two elements, C<$x[$#x-1]> and C<$x[@x-2]> are
equivalent to $x[-2]. But if it contains a single element, C<$x[$#x-1]>
and C<$x[@x-2]> are equivalent to $x[-1]. Simply put, the preferred form
is more likely to do what you actually want.
As Conway points out, the preferred forms also perform better, are more
readable, and are easier to maintain.
This policy notices all of the simple forms of the above problem, but
does not recognize any of these more complex examples:
$some->[$data_structure]->[$#{$some->[$data_structure]} -1];
my $ref = \@arr;
$ref->[$#arr];
=cut
As for the short message, it's hard to be very nuanced in just one line.
You say that the short message gives the impression that the different
forms are equivalent, but it seems to me that "Negative array index
should be used" is silent on whether they are exactly equivalent.