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

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

use strict; use 5.010; foreach my $word (qw(abc def ghi)) { say $word; }
When using strict perl requires to declare even the loop variable of a foreach loop. Why is that? After all the $word variable in the above example is an alias to the values and won't have any effect outside of the loop. Even if written this way:
use strict; use 5.010; my $word = "hello"; foreach $word (qw(abc def ghi)) { say $word; } say $word; # word is "hello" here
Why is this code not allowed?
use strict; use 5.010; foreach $word (qw(abc def ghi)) { say $word; } # generate syntax error if $word is used here

Replies are listed 'Best First'.
Re: why need my in a foreach loop?
by ikegami (Patriarch) on Nov 28, 2010 at 04:55 UTC

    When using strict perl requires to declare even the loop variable of a foreach loop.

    It can use package variables, for starters.

    our $foo; sub f { print("$foo\n"); } for $foo (qw( a b c )) { f(); # Prints a, b and c. }

    Foreach loops existed long before "my".

    Why is this code not allowed?

    It generates an error for all instances of $word since you never declared it and you asked to make such things errors.

      Here's the difference:

      use strict; use warnings; use 5.010; our $foo = 'hello'; sub f { print("$foo\n"); } for my $foo (qw( a b c )) { f(); } --output:-- hello hello hello

      In ikegami's example, the my is omitted in the for loop, which causes the for loop to change the global variable $foo--and the subroutine prints the global $foo (i.e. the subroutine is a closure).

        the subroutine is a closure

        Backwards. It works because the subroutine doesn't capture package variables. If you switched our for my in my snippet, you'd have a closure, and you'd get a different result.

Re: why need my in a foreach loop?
by moritz (Cardinal) on Nov 28, 2010 at 07:47 UTC
    use strict 'vars' basically says "all variables that you use must be declared (unless they contain :: or ').

    Using a variable in a loop is not different from using a variable in an assignment: it can either use an existing one, or it can be a fresh one, declared with my.

    Or put another way: use strict; forces you to be explicit about your declarations. Having some construct doing implicit declarations, at least in some circumstances, goes against the entire idea of strict.

    Update: Perl 6 gets around this by having other declarative syntax forms. Signatures can be used for that, either by being attached to a routine, or in the form of a lambda:

    # | declares $x in the scope of the block my $lambda = -> $x { $x * $x } # reused in loop syntax: for <a b cd> -> $x { say $x } # | declares $x in the scope of the block sub square($x) { $x * $x }
      apparently most people thought here I don't understand that use strict (or more specifically the 'vars' part of it) forces the need of "my". My question why do we need that in a for-loop.

      As you also know way better than I, Perl 6 can get by without this. I don't see when does that "my" do any useful work there. It is not the "my" that defines the scope of this variable so IMHO it is there only to satisfy "use strict".

        It is not the "my" that defines the scope of this variable so IMHO it is there only to satisfy "use strict".

        I can't think of any other cases in which Perl 5 automatically lexicalizes a named variable without my; I think it's a (useful) consistency.

        I love that in Perl6 loops automatically create localized variables: (may look familiar to Gabor)

        for @names -> $n { say $n; }

        Why not backport that feature into Perl5. Maybe only if warnings and strict and features are full on.<?p>

        As Occam said: Entia non sunt multiplicanda praeter necessitatem.

Re: why need my in a foreach loop?
by JavaFan (Canon) on Nov 28, 2010 at 12:08 UTC
    In the old days of perl5,
    foreach my $var (LIST) { .. }
    was a syntax error. You had to write:
    my $var; foreach $var (LIST) { .. }
    or use a package variable, as pointed out earlier in this thread.

    I remember the days that

    foreach my $var (LIST) { .. }
    was actually seen as progress...
Re: why need my in a foreach loop?
by PeterPeiGuo (Hermit) on Nov 28, 2010 at 06:09 UTC

    Why not? What's the benefit of not requiring this? What's the benefit of not having consistent rule here?

    Peter (Guo) Pei

      The OP points out that there's no real difference between for $lex (...) and for my $lex (...). The "my" is just useless noise. As such, the declaration could be implicit.

      It's reasonable, but it's not true because foreach loops don't just work with lexicals.

        The foreach loop always works with an alias. IMHO the variable is never connected to anything outside the for loop so the values never "leak" out of the loop. If I am mistaken, please give an example when that variable is connected to something else as well.