http://www.perlmonks.org?node_id=743644

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

I read with interest the post, here. It discusses the scope of the indexing variable in "for" and "foreach" loops. At a working level of understanding, the indexing variable is localised to the loop. It says in the man page that "foreach" is a synonym for "for".

However, "for" is not always a synonym for "foreach". Care must be used if one is to say it's a "misspelling" or they can be used "interchangeably". "For" looks to behave differently depending on it's context: c-style vs. (er) foreach-style. If one uses c-style "for" loops you don't always get localised indexing variables as you seem to in "foreach" loops.

UPDATE: the above paragraph is wrong - "for" and "foreach" can be used interchangeably. The key point for me is that "for" is overloaded and behaves differently depending on the form of the arguments. ikegami's response sums it all up nicely in my opinion. Ironically "foreach" which is supposed to (and does) aid the programmer by letting him know explicitly what form of "for" is being used, tricked me into thinking about it in a weird way.

Anyhow, I'm interested in why Perl has the two styles of "for" constructs: convenience to the programmer seems the likely answer? I certainly appreciate the "foreach" loop. I'm assuming the "foreach" loop came after the "c-style for" loop - is this the correct Perl history? And if so, why was "foreach" implemented in a way such that the indexing variable is localised. Was this an ease of implementation decision or something else?

Replies are listed 'Best First'.
Re: For vs. Foreach
by ikegami (Patriarch) on Feb 13, 2009 at 17:56 UTC

    Care must be used if one is to say [...] they can be used "interchangeably".

    The keywords can be used interchangeably. Any difference is purely stylistic.

    Anyhow, I'm interested in why Perl has the two styles of "for" constructs

    Three kinds of loops use for/foreach as far as I'm concerned:

    • Counting loop: for[each] [VAR] (EXPR .. EXPR)
    • Iterative loop: for[each] [VAR] (LIST)
    • C-style for loop: for[each] (EXPR; EXPR; EXPR)

    The following iterative loops are optimised in one way or another:

    • for[each] (@array)
    • for[each] (reverse @array)
    • for[each] (reverse EXPR .. EXPR)
    • for[each] (reverse CONST_EXPR .. CONST_EXPR)

    "For" looks to behave differently depending on it's context: c-style vs. (er) foreach-style. If one uses c-style "for" loops you don't always get localised indexing variables as you seem to in "foreach" loops.

    That's either unclear or wrong.

    C-style for loops (whether written with for or foreach) don't localise the index variable simply because they don't accept an index variable.

    However, you are free to declare variables in all three of its control expressions, and they will be scoped to the loop.

      I'm curious why you consider the "counting loop" to be a fundamentally different kind of loop, instead of listing it among the optimised iterative loops. Is there any difference as far as observable behavior, or is it just that it's implemented differently, or is there really no difference but that's how you conceive of it?

        Good question.

        It is truly optimised to count from the first to the last without creating a list. You could lump it as an optimisation since the effect is the same as if ".." was the range operator. (It's not.) I choose not to.

        People already have a concept of a counting loop from countless other languages. They expect to find a counting loop and presume Perl provides the C-style for loop that purpose. I'm giving them what they are looking for.

        By labeling it as a counting loop, I try to clear the false perception that it should be avoided for efficiency reasons, in order to encourage the use of the for my $i ($x..$y) over the less readable for (my $i=$x; $i<=$y; ++$i).

Re: For vs. Foreach
by moritz (Cardinal) on Feb 13, 2009 at 17:48 UTC
    They are synonyms, and you can find that out with B::Deparse:
    $ perl -MO=Deparse -e 'foreach (1..2) { }' foreach $_ (1 .. 2) { (); } -e syntax OK $ perl -MO=Deparse -e 'for (1..2) { }' foreach $_ (1 .. 2) { (); } -e syntax OK

    So they produce the same optree

Re: For vs. Foreach
by Joost (Canon) on Feb 13, 2009 at 17:45 UTC
Re: For vs. Foreach
by tilly (Archbishop) on Feb 13, 2009 at 17:28 UTC
    Can you offer a code example where for and foreach behave differently?

    (And if you can do so, you might wish to use perlbug to report the bug that causes them to differ...)

      Peeking in toke.c suggests there is one difference between 'for' and 'foreach'. It seems it's valid to use 'for' somewhere in an attribute declaration. The documentation about attribute doesn't make it clear to me how. Best thing I can do is generating different error message when using 'for' or 'foreach':
      $ perl -wE 'sub foo: foreach' Invalid CODE attribute: foreach at -e line 1 BEGIN failed--compilation aborted at -e line 1. $ perl -wE 'sub foo: for' syntax error at -e line 1, next token ??? Execution of -e aborted due to compilation errors.
      Using 'for' is a compile time error, using 'foreach' a run time error (resulting in abortion of the compilation).

      If someone could show how to use 'for' inside an attribute, that would be dandy.

        You're right!
        use Attribute::Handlers; sub foreach :ATTR { print "Just another Perl hacker,\n"; } sub foo :foreach {} foo();
        prints the expected, while
        use Attribute::Handlers; sub for :ATTR { print "Just another Perl hacker,\n"; } sub foo :for {} foo();
        does not. I'll follow my own advice and send a perlbug.