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

Simple question about foreach and my.

by Xxaxx (Monk)
on Mar 27, 2001 at 18:02 UTC ( [id://67492]=perlquestion: print w/replies, xml ) Need Help??

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

Now that I'm past the arch newbie stage I'm trying to clean up my code... It's come to my attention that apparently my foreach loops should be done different.
foreach $var (@somearray) { .... }
apparently should be:
foreach my $var (@somearray) { .... }
Can I take this as a universal? Or, are there obvious situations in which this use of the my is not appropriate? Claude

Replies are listed 'Best First'.
Re: Simple question about foreach and my.
by davorg (Chancellor) on Mar 27, 2001 at 18:22 UTC

    Well, you should always declare your variables using the appropriate mechanism (usually my) or otherwise your script won't run under use strict.

    The choice is not, therefore, between using or not using my, rather where's the best place to put the my. You can either do

    foreach my $var (@array)

    or

    my $var; foreach $var (@array)

    The first has the advantage that the scope of the variable is restricted to your foreach loop and in the second example the variable scope is the scope that contains the loop. However, the first syntax was introduced relatively recently (5.005 or thereabouts), so if you are running on older versions of Perl (and you shouldn't be) then you'll be forced to use the second method.

    --
    <http://www.dave.org.uk>

    "Perl makes the fun jobs fun
    and the boring jobs bearable" - me

      I believe that 5.004 introduced it.

      In older Perl's I write like this:

      foreach (@array) { my $var = $_; # ... }
      which keeps the loop variable private. (At the cost of opening yourself up to wiping out your array if you call something that walks over $_ unexpectedly.)
      What about variables used within the loops (style, speed, etc.). Do you prefer:
      foreach my $var (@array) { my $other_var = .... etc. }
      or
      my $other_var; foreach my $var (@array) { $other_var = .... etc. }

        Depends completely on what I'm going to do with the variable. The overriding principle is that a variable is scoped as tightly as possible.

        If the variable is only used within the loop then it should be restricted to within the loop. If I'm going to use it outside the loop then I'll declare it outside the loop.

        --
        <http://www.dave.org.uk>

        "Perl makes the fun jobs fun
        and the boring jobs bearable" - me

Re: Simple question about foreach and my.
by arhuman (Vicar) on Mar 27, 2001 at 18:06 UTC
    I find the 'my' form better, for several reasons...
    (speed, style...)

    But I've seen a lot of experienced programmers using the older form (without my).
    (By example, in the Advanced Perl Programming almost all examples don't use 'my')

    NOTE : I should add that the speed aspect is only minor,
    and this case is one of the (rare) special case where you can use 'my' without making a long code unbearable...
    A good discussion on 'my', its danger, its speed gain and optimization could be find here.

    "Trying to be a SMART lamer" (thanx to Merlyn ;-)
Re: Simple question about foreach and my.
by Masem (Monsignor) on Mar 27, 2001 at 18:51 UTC
    As others have put it, it's a matter of scoping, both are correct for 99.9% of the cases out there. But, as an example of where you'd want to have the my statement elsewhere of the foreach statement:
    my $element; foreach $element (@set_of_numbers) { last if $element < $critical_value; } print "$element is below the critical value.\n";
    If the my was inside the foreach, $element would not have scope outside the loop, and therefore you'd run into problems with the print statement.
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
      Actually, I don't think that works. The reasoning is that since $_ is local'ed inside foreach loops, any loop variable should be. This is supposedly in support of the principle of "least surprises". Anyway, with 5.05003 I get:
      > perl -lwe '$x=$y=0; foreach $x (0..9) { ++$y } print "$x, $y"' 0, 10 > perl -lwe 'my($x,$y)=(0,0); foreach $x (0..9) { ++$y } print "$x, $y +"' 0, 10 > perl -lwe '$y=0; foreach $x (0..9) { ++$y } print ! defined $x,", $y +"' 1, 10 > perl -lwe 'my $y=0; foreach my $x (0..9) { ++$y } print ! defined $x +,", $y"' Name "main::x" used only once: possible typo at -e line 1. 1, 10 >


      p
Re: Simple question about foreach and my.
by THRAK (Monk) on Mar 27, 2001 at 18:35 UTC
    In some case I find it easiest to not even use a variable, but rely on your friend: $_

    foreach (@somearray) { s/for_this/sub_this/g; }


    There are many times when this is useful. This might not be the best example but it is one possible use. In this case to do a substitution in each array entry. I think a bigger point would be that you have found your way to "use strict". A definate thing you should always do.

    THRAK
      You need to be very careful using this idiom, especially if you're hoing to embed loops. It's very easy to mix up which $_ belongs to which loop and create some horrendous problems.

      In general I find it's better to name (and declare) the iteration variables unless it's really going to be a short loop (in which case I tend to use the statement modifier expr for (@array) in any case)

Re: Simple question about foreach and my.
by Xxaxx (Monk) on Mar 27, 2001 at 19:03 UTC
    Thank you all for the totally excellent suggestions. Claude

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://67492]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2024-04-25 23:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found