Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Scoping of my with foreach loop

by uksza (Canon)
on Mar 07, 2005 at 19:05 UTC ( [id://437285]=perlquestion: print w/replies, xml ) Need Help??

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

Hello wise monks,

Is any difrence between
my $item; foreach $item (@array) and foreach my $item (@array)

stay in peace, sisters and brothers

Lukasz

20050308 Edit by castaway: Changed title from 'my ()'

Replies are listed 'Best First'.
Re: Scoping of my with foreach loop
by BrowserUk (Patriarch) on Mar 07, 2005 at 19:29 UTC

    It doesn't make a lot of sense to use a loop variable that was previously declared, because the one that gets used within the loop is (temporarally), an entirely different variable, despite that it has the same name:

    my $i = -23; for $i ( 1 .. 10 ) { print $i; last if $i == 5; } print $i; 1 2 3 4 5 -23

    Doing so tends to make look as if $i will retain the last value used in the loop, but as you can see, it doesn't.

    It caught me out a couple of times and is something that I hope will not persist into Perl6.

    In fact, I think I would change it in perl 5.10. Any code that got bitten by the change in behaviour would be better changed anyway.


    Examine what is said, not who speaks.
    Silence betokens consent.
    Love the truth but pardon error.
Re: Scoping of my with foreach loop
by dragonchild (Archbishop) on Mar 07, 2005 at 19:08 UTC
    Yes. In the second, $item is scoped only to the loop. In the first, $item is scoped outside the loop. You would use the second first if you want to access the value of $item outside the loop. As in
    my $item; foreach $item (@values) { last if $item =~ /Some Complicated Regex/; } do_something_with( $item );

    Update: Fixed typo as per Fletch's /msg.

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

      Not quite.

      do_something_with( $item );
      will always be the same as
      do_something_with( undef );
      in your code. foreach restores the initial value when the loops exits (in effect), as seen in the following snippet:

      use strict; my @values = (1, 2, 3, 'a', 4); my $item = 'z'; foreach $item (@values) { last if $item =~ /[^\d]/; } print($item); # Prints 'z', not 'a'.

      I thought it might be using a localized global when my is omitted, but it's clearly not the case:

      This is perl, v5.6.1 built for MSWin32-x86-multi-thread
Re: Scoping of my with foreach loop
by ikegami (Patriarch) on Mar 07, 2005 at 19:24 UTC

    The difference can be observed by running the following two snippets.

    use strict; my @array = (1, 2, 3); my $item = 'z'; foreach $item (@array) {} print($item); # Prints 'z' (not '3'!!!).
    use strict; my @array = (1, 2, 3); foreach my $item (@array) {} print($item); # Compile error. $item only in scope for loop.
Re: Scoping of my with foreach loop
by Fletch (Bishop) on Mar 07, 2005 at 19:09 UTC

    Missing $ sigils aside: In the first example $item is visible outside and after the for BLOCK; in the second $item is only visible within the for BLOCK.

Re: Scoping of my with foreach loop
by mikeB (Friar) on Mar 07, 2005 at 19:12 UTC
    Neither will compile? No, wait. That's a similarity. :)

    Assuming you meant $item in each case, the difference would be in the scope of $item. In the second case it would be limited to the foreach block.

Re: Scoping of my with foreach loop
by Popcorn Dave (Abbot) on Mar 07, 2005 at 19:17 UTC
    Other than it won't compile? You need to make that $item.

    And yes you could concievably run in to scoping issues. Someone else will correct me if I'm incorrect about this but I believe that if for example, you declare my $item at the top of your program, then it's got global scope. However if that foreach loop was placed in a subroutine then it's going to be local to that routine and you wouldn't have access to it outside the loop.

    If both of those are at the top of a script, then there shoudln't be any difference.

    Update:Fletch picked up what I failed to take in to account completely about being visible within the foreach loop.

    Useless trivia: In the 2004 Las Vegas phone book there are approximately 28 pages of ads for massage, but almost 200 for lawyers.
Re: Scoping of my with foreach loop
by cog (Parson) on Mar 07, 2005 at 19:50 UTC
    Also, the first version tends to be faster, because the second one has to declare a new variable for each element of @array (unless this has been optimized by now).

    Benchmark it with a big array.

      use Benchmark; my @array = (1..999999); timethis (200, sub { my $foo; for $foo ( @array ) { 1; } }); timethis (200, sub { for my $foo ( @array ) { 1; } }); #timethis 200: 33 wallclock secs (31.58 usr + 0.02 sys = 31.60 CPU) @ + 6.33/s (n=200) #timethis 200: 32 wallclock secs (31.65 usr + 0.04 sys = 31.69 CPU) @ + 6.31/s (n=200)
      seems to be optimized (perl 5.8.6)


      holli, /regexed monk/

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (8)
As of 2024-04-25 11:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found