It's our classic idiom for loops:

for($i=0;$i<10;$i++) { &do_something; }

However, when we actually start to use the index,

for($i=0;$i<10;$i++) { &do_something($i); }
we frequently see various addenda to get it from "0 - 9" to "1 - 10".
for($i=0;$i<10;$i++) { &do_something($i + 1); }

Luckily, in perl, we have the flip-flop '..' to make things look like

for $i (1..10) { &do_something($i); }
which allows us to stop resorting to index manipulation.

If we do not need the zero, then why shouldn't we change the base? You know, $[, that fun yet spooky variable? Yes, making changes to it is not recommended. It might break a good number of things, and changing is now considered a compiler directive, so why make it available?

What's your opinion? -v
"Perl. There is no substitute."

Replies are listed 'Best First'.
Re: The Zeroeth Principle
by tilly (Archbishop) on Aug 25, 2004 at 16:24 UTC
    Why do you say "our" and "we"? I'm clearly not part of the intended audience. Here are some coding tips that may help you no longer be part of the intended audience either.

    First suggested change, start declaring all of your variables with my. That allows you to start using strict.pm.

    Second suggested change, never call &do_something without parentheses unless you really want the @_ aliasing. If you don't know what I mean, then trust me that you didn't want to do that.

    Third, don't write C-style for loops without specific reason. One of the most common bugs in C is off-by-one errors in a loop. (Yes, even for very experienced people. Track yourself.) Using C-style loops is going to cause you to have the same errors in Perl.

    Fourth, avoid action at a distance. Trying to remember whether you've played with $[ will cause even more off-by-one mistakes. Learn how Perl likes to work, and stick with that. You'll have fewer errors. (And will be less likely to break any modules that you want to load.)

    Fifth, learn the difference between the range and flip-flop operators. Yes, list vs scalar context can be confusing. But in Perl it is also very important.

    Sixth, always say what you want directly. If you want to loop over 1..10 you can do that directly with either looping style. Just do it.

    And last, but not least, if you want to loop over an array, at least 95% of the time it is best to just do it directly and forget about what the index is:

    for my $thing (@stuff) { do_something($thing); }
    (Note that I don't use the & on the function call. That is intentional, but it is a minor style decision of mine allowing me to be more consistent across languages. It isn't an important preference.)
      1. This was just a rough example. I always use strict, use warnings, and declare everything.
      2. I called the function without parenthesis, because it's a trivial example. I know what it does. This was just for display purposes.
      3. In perl, I have rarely ever needed anything akin to a c-styled loop. This was for simply to promote discussion. I'm happy to see it worked! :-) Such passion!
      4. Action at a distance is not good. I never do that in my own code.
      5. I mistyped. I rarely refer to the operator by name, so I said flip-flop instead of range. Believe me, I'm very well aware of list vs. scalar vs. void contexts. :-)
      6. Yes, I know. This was more to promote discussion about a strange little variable.
      7. Most of the time, I do not need an index, and so I interate over the list directly. That is the perl way to do it, after all. When I do need an index, I'm exceedingly careful about its use, and exploit the range operator to it fullest, especially since it no longer slugs memory in the gut with large ranges. Mind you, in the before time, or when performance plays an issue, simple things like moving a complicated conditional to the initializer, and runnign the loop "backwards" was a key to efficiency.

      And the "our" and "we" at the top referred to a simple commonality of brethren programmers...the universal "we" in a spirit of rememberance.

      I'm quite happy this little meditation has provoked much thought, although I didn't expect a lesson on stylistics. Thanks! I was more curious as to the treatment of the $[ operator by those who have used it.

      Cheers!
      -v
      "Perl. There is no substitute."
        I don't know what your usual style is. However experience indicates that the way people write "toy code" is the way that they write real code as well. Therefore I reacted to aspects of your style which I thought likely to show up in real code.

        As for the treatment of $[ by those who have used it, the wise ones don't use it any more. ;-) My understanding is that $[ was added to Perl so that a2p could use it to easily emulate awk without having to track down every potential array access.

Re: The Zeroeth Principle
by dragonchild (Archbishop) on Aug 25, 2004 at 15:48 UTC
    From Programming Perl, 2nd ed., p. 657:

    ... Default is 0, but we used to set it to 1 to make Perl behave more like awk (or FORTRAN) when subscripting and when evaluating the index and substr functions. ...

    Basically, it was a (mis)feature that was caught and made safer, but left in for backwards compatability. I wouldn't expect to see it in Perl6.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

Re: The Zeroeth Principle
by hardburn (Abbot) on Aug 25, 2004 at 16:47 UTC

    There are times where you really need an index. However, this may not be as often as you think.

    In nearly all cases, you are iterating through an array:

    for $i ( 0 .. $#array ) { print $array[$i]; }

    But Perl (and a surprising number of other languages, particularly functional ones) provide a way to do it without the index:

    for $i (@array) { print $i; }

    I'm told that there are even some langauges that have no way of indexing an array at all.

    So when people get into debates about 0-vs-1 array indexes, or if array names should not be pluralized so that $list[1] reads better, I must wonder how often these people are using indexes. I would argue that using a lot of indexes is a result of a coder who doesn't really know the language. If you're not using array indexes, then why do you care if the array is indexed at 0 or 1 in your particular language? Why would you care if your language has indexes at all?

    One of the few places where I do use indexes is in debugging--I sometimes want to know that the error occured at a certain spot in the array. Also, I use them when parsing xSV files, since I often want a specific entry in the given row.

    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

      If you don't have indices, you can't have slices, you can't splice, and you wouldn't be able to do a binary search, and you won't be able to use a Schwartzian Transform in the way you are used to do it now. Basically, if you give up indices, you give up random access into arrays, and you're downgrading arrays to linked lists. I'm very glad I don't program in languages that don't give me the full power of arrays.

        I don't necessarily advocate getting rid of indexes entirely, only note that it's possible. You're right, it would give up some powerful features (but not Turing Completeness).

        "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

      Most people would just write:
      print @array;
      and don't bother with the C-style vs. alias style discussion.
Re: The Zeroeth Principle
by eric256 (Parson) on Aug 25, 2004 at 15:41 UTC

    Just a few additions/thoughts. In list context like that is called the range operator and has a totaly different fucntion than the flip-flop scalar operator. Also i would consider the use of it the idiom for perl programers, and the

    for($i=0;$i<10;$i++) { &do_something($i); }
    form a leftover from c. It may have its uses but its far hader to read. Also if you want the above loop from 1 to 10 just do
    for($i=1;$i<=10;$i++) { &do_something($i); }
    Thats easier to read than $i + 1 and actualy does what you want it to instead of tweaking it.


    ___________
    Eric Hodges
Re: The Zeroeth Principle
by talexb (Chancellor) on Aug 26, 2004 at 14:09 UTC

    If you want to affect the elements 1..10, you could set $[ to 1 and iterate from 0 to less than ten, as your code describes. That seems like a contrived example to me. What problem are you trying to solve?

    I fiddled with $/ for the first time yesterday in order to read in a file in one big slurp, but I generally leave the 'system dollar' variables alone.

    In any case, I believe $[ is going away in Perl 6 -- so it's probably best not to get into the habit of using it anyway.

    Alex / talexb / Toronto

    "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds