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

long time reader first time caller....
Anyway, i'm currently upgrading some legacy scripts to perl 5.10. There's a lib we've got that for some reason decided it'd be easier if arrays started at 1, so they've gone and set $[ = 1
They've done this in a module, in an init function. The code has previously run in 5.8.8, and i'm updating everything to use perl 5.10.
my test.pm example:
#!/usr/bin/env perl package test; sub Init { $[ = 1; } sub test { print "(\$[= $[) array has " . scalar @_ . " elements, last index += $#_\n"; } 1;
t1.pl:
#!/usr/bin/env perl use test; test::test(1,2,3,4); # test::Init(); test::test(1,2,3,4);
As it turned out, even without calling test::Init, the mere fact that that is in that function has somehow globally turned on that option...
in perl 5.8.8, i execute the t1.pl and get:
# perl 5.8.8 output ./t1.pl ($[= 1) array has 4 elements, last index = 4 ($[= 1) array has 4 elements, last index = 4
and in perl 5.10
# perl 5.10 $ ./t1.pl ($[= 0) array has 4 elements, last index = 3 ($[= 0) array has 4 elements, last index = 3
regardless of whether i call Init or not. I'm not sure why this happens, and it looks like it was a bug in perl 5.8.8 that wasn't listed as resolved in perl 5.10 but is...
It drove me crazy :| hopefully this information at least helps someone if they see the same thing - i've not seen it listed anywhere as a change or as something someone has tripped over. Can anyone else confirm this or is it just me? :|

Replies are listed 'Best First'.
Re: fun with $[
by ikegami (Patriarch) on Aug 06, 2008 at 03:44 UTC

    In 5.8.8, it behaves as documented. Quote 5.8.8's perlvar:

    As of release 5 of Perl, assignment to $[ is treated as a compiler directive [...]. (That's why you can only assign compile-time constants to it.)

    In fact, 5.10.0's perlvar still includes that line, so you've uncovered a bug. (Documentation or code bug, I don't know.)

Re: fun with $[
by parv (Parson) on Aug 06, 2008 at 02:21 UTC
    I see the same behaviour as listed with 5.8.[78] & 5.10.0. Try also Deparse (perl -MO=Deparse file) ...
    # test.pm was used in p.pl. # # perl 5.10.0 package test; sub Init { $[ = 1; BEGIN { $^H{'$['} = q(1); } $[; } sub test { $[ = 0; print '($[= 0) array has ' . scalar(@_ . " elements, last index = +$#_\n"); } '???'; test.pm syntax OK use test; test::test(1, 2, 3, 4); test::Init(); test::test(1, 2, 3, 4); p.pl syntax OK # perl 5.8.7 package test; sub Init { $[ = 1; } sub test { print '($[= 1) array has ' . scalar(@_ . " elements, last index = +$#_\n"); } '???'; test.pm syntax OK use test; $[ = 1; test::test(1, 2, 3, 4); test::Init(); test::test(1, 2, 3, 4); p.pl syntax OK
Re: fun with $[
by syphilis (Archbishop) on Aug 06, 2008 at 02:39 UTC
    Of $[, the perlvar documentation says "Its use is highly discouraged".
    And what better way to discourage its use than have it behave in the way you've presented :-)

    Cheers,
    Rob
Re: fun with $[
by Perlbotics (Archbishop) on Aug 06, 2008 at 14:23 UTC
    Maybe it is an option for you to localise the $[ like so?
    !/usr/bin/perl use strict; package LocalBlock; { # localisation scope local $[ = 1; sub test { # now a closure print "(\$[= $[) array has " . scalar @_ . " elements, last index = $#_ (", join(", ", @_) , ")\n"; } } # end of scope 1; package main; print "Pre: \$\[ = $[ \n"; LocalBlock::test(1,2,3,4); print "Post: \$\[ = $[ \n\n"; $[ = 5; print "Pre: \$\[ = $[ \n"; LocalBlock::test(5,6,7,8); print "Post: \$\[ = $[ \n\n"; __END__ Pre: $[ = 0 ($[= 1) array has 4 elements, last index = 4 (1, 2, 3, 4) Post: $[ = 0 Pre: $[ = 5 ($[= 1) array has 4 elements, last index = 4 (5, 6, 7, 8) Post: $[ = 5
    Cannot test it without 5.10 here, sorry.
Re: fun with $[
by JadeNB (Chaplain) on Aug 20, 2008 at 21:05 UTC
    I don't understand why it would behave differently in Perl 5.8.8, but the following paragraph from perldata seems consistent with the Perl 5.10 behaviour you've described:
    Version 5 of Perl changed the semantics of $[: files that don't set the value of $[ no longer need to worry about whether another file changed its value. (In other words, use of $[ is deprecated.) So in general you can assume that
    scalar(@whatever) == $#whatever + 1;
    (I know this is an old question by now, but I was looking for this line that I vaguely remembered in perldelta, not perldata.)