Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

$[ is under respected.

by EvanCarroll (Chaplain)
on Aug 03, 2005 at 02:34 UTC ( #480333=perlmeditation: print w/replies, xml ) Need Help??

This venerable variable demands more respect than many monks give it. Its might and glory are rarely actualized and this is a detriment to the perl community.

Observe this variables willingness to be noticed.
$[++; # No go. $[+=1; # Not happening $[ = $[; # Works. $[ = $[ + 1; # That will work! print \$[; # Ok, works. $[ = \$[; # which also works print $[; # Whoo fun!
Take notice to 'print \$[;' not to be confused with '$[ = \$[; print $[;', but the fun doesn't stop here monks!
$[=-1; @_=qw/foo bar baz/; print $_[-1]; # foo print $_[-2]; # bar print $_[-3]; # foo
After playing with $[; I have taken note to this dire mistake that I apparently have made habit. And, now I have decided to publish a finding to enlighten all. This idiom is wrong, and must be corrected at all cost.
#WRONG: for(my $i=0; $i<$#foo; $i++){} #RIGHT: for(my $i=$[; $i<$#foo; $i++){}

However, for the same reason this idiom is also wrong:
#WRONG: foreach(0..$#foo){} #RIGHT: foreach($[..$#foo){}
Now that two bad commonplace practices have been exposed, I suggest that we enable warnings to be issued for people who use the 0..$#foo. These willy-nilly coding practices are detrimental should be discouraged. I see them much more severe than addressing an element with the array sigil, at least Perl can correct for that.

Evan Carroll

Replies are listed 'Best First'.
Re: $[ is under respected.
by duff (Parson) on Aug 03, 2005 at 05:25 UTC

    I hope your post is in jest. If you were tchrist, it would clearly be hilarious. :-) But since I don't know you and it's hard to tell in this low-bandwidth, high-latency medium ...

    You're about 10 years too late. The perl community has used $[ and found it painful, ergo it is soon to be extirpated.

    BTW, you've got the first idiom wrong. It is:

    for (my $i = 0; $i < @array; $i++) { ... }
      BTW, you've got the first idiom wrong. It is: for (my $i = 0; $i < @array; $i++) { ... }

      No, the correct idiom is usually

       for my $elt (@array) { ... }

      or, in those rare cases where you really do need an index into the array, it becomes

      for my $i (0 .. $#array) { ... }

      C-style three-clause for loops have been deemed unperlish, are deprecated, and have been removed from the core language in Perl6. If you really need the ability to manipulate the loop variable from within the loop, beyond what next and last provide, then use a while loop, but in general it's best to avoid that if possible. (Avoid using while loops in that way, I mean, not avoid using them at all.)

        C-style three-clause for loops have been deemed unperlish, are deprecated, and have been removed from the core language in Perl6.

        The C-style for loop hasn't been removed from perl6, it's just been renamed:

        loop my $i = 0; $i < $n; $i++ { ... }
        See S04

        And the C-style for loop has hardly been deemed "unperlish". If anything, it's unperlish for this particular purpose (iterating over an array index). It's certainly useful in other situations (though, in perl6, many of those situations are satisfied by other, newer language features)

Re: $[ is under respected.
by tlm (Prior) on Aug 03, 2005 at 12:30 UTC

    I have a hard time coming up for good reasons ever to change $[ from its default.

    The only situation I can imagine, and it's a very farfetched one, is if I am translating from a non-zero-based indexing language (like Fortran) into Perl some extremely complex algorithm that I barely understand and that has lots of array index manipulations. In such a rare situation, for the sake of avoiding translation mistakes I may set $[ to 1. But even this would be temporary; ultimately, with a sufficiently solid test suite to back me up, I'd refactor the whole thing to 0-based indexing.

    I'd be curious to know if any other monk has found any other use for a non-zero $[.

    the lowliest monk

      Actually, your "far fetched" idea is close to the reason why Perl has $[. It's not so for porting non-Perl code to Perl, but for porting non-Perl programmers to Perl. In its early days, Perl didn't have many users, and it needed to recruit programmers who were familiar with other languages. Fortran for instance, but more likely, awk.

      I sometimes use $[. Whenever I find myself using -1 and +1 to switch to and from computer and human counting, I consider telling the computer to adapt to humans, and use $[. So instead of:

      for my $x (0 .. $X - 1) { for my $y (0 .. $Y - 1) { # Do something with $array[$x][$y] printf "bla, bla (%d, %d)", $x + 1, $y + 1; } }
      So I may write:
      { local $[ = 1; for my $x (1 .. $X) { for my $y (1 .. $Y) { # Do something with $array[$x][$y] print "bla, bla ($x, $y)"; } } }

      I was recently attempting to implement an algorithm for continued fractions, in which the subscript of the variables was negative. It occurred to me that it might be convenient to fudge the index to make the implementation easier for me.

      (Un)fortunately, I didn't know about $[, so I was compelled to actually understand the algorithm and write code so that Perl would be happy.

      I think this is something like the Perl philosophy, not constraining people to follow a particular path. It's nice to know I *could* move the index, if I wanted to - even though I understand that if I ever did that, I'd likely be sorry...

      A reply falls below the community's threshold of quality. You may see it by logging in.
Re: $[ is under respected.
by itub (Priest) on Aug 03, 2005 at 02:57 UTC
    I personally never use $#foo; I prefer scalar @foo. For example,
    for (1 .. @foo) {}
      You still suffer from the same problem, you assume that 1 is the begining of the array, and that scalar(@arr) == ($#arr+1). That makes you dually wrong if $[ = 1;

      Evan Carroll

        Yes ... but don't do that. Having $[ set to anything other than 0 is just asking for a world of trouble. Most modules won't cooperate, for starters. Having a global variable define the lower-bound of your arrays is going to give you issues. The right way to do this in any script of reasonable length (e.g., uses any other modules) is to be able to specify on a variable-by-variable basis what the minimum (and, optionally, maximum) index(es) is(are). Which is how any other language of note does it, if they do it at all.

        Perhaps perl6 will have that. But perl5 doesn't, so don't do that.

          A reply falls below the community's threshold of quality. You may see it by logging in.
        A reply falls below the community's threshold of quality. You may see it by logging in.
        Not really, for (1 .. @foo) will always loop once per array element. Where did I say that I intended to use $_ as an index to get at the elements of @foo? ;-)
Re: $[ is under respected.
by Anonymous Monk on Aug 03, 2005 at 09:05 UTC
    Does anyone understand this:
    my @foo = qw /foo bar baz quux/; $[ = 2; print $foo[2], "\n"; print $foo[1], "\n"; print $foo[0], "\n"; __END__ foo quux foo
    If $[ is set to 2, $foo[2] is the first element (foo). It seems that $foo[1] is the last element (quux), which is logical because 1 == $[ - 1. But while 0 == $[ - 2, $foo[0] isn't equal to penultimate element (baz), but it's equal to the first element (foo) - as if $[ doesn't effect an index equal to 0.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://480333]
Approved by greenFox
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (2)
As of 2022-05-28 01:39 GMT
Find Nodes?
    Voting Booth?
    Do you prefer to work remotely?

    Results (98 votes). Check out past polls.