global my() variable used in foreach() loop loses its value 
Author Message
 global my() variable used in foreach() loop loses its value

Here's a Perl script whose behavior I don't understand at all.

I am using a global variable, declared my() at the top level, as
the loop control variable in a "foreach" loop.  Inside the loop,
I call a subroutine which access the global variable.  Instead
of getting the expected value of the variable, it instead finds
the variable to be empty.   Why?

*****  The perl script ********

#!/usr/local/bin/perl -w

use strict;
my $topic;

main();

sub main {


        print "In loop: topic is $topic\n";
        subroutine();
    }

Quote:
}

sub subroutine {
    print "In subroutine: topic is $topic\n";

Quote:
}

******* The output **********

In loop: topic is first
Use of uninitialized value at /tmp/foo.pl line 18.
In subroutine: topic is
In loop: topic is second
Use of uninitialized value at /tmp/foo.pl line 18.
In subroutine: topic is
In loop: topic is third
Use of uninitialized value at /tmp/foo.pl line 18.
In subroutine: topic is
In loop: topic is fourth
Use of uninitialized value at /tmp/foo.pl line 18.
In subroutine: topic is

******  end of output *******

If I remove these two lines:

  use strict;
  my $topic;

the program behaves properly:

In loop: topic is first
In subroutine: topic is first
In loop: topic is second
In subroutine: topic is second
In loop: topic is third
In subroutine: topic is third
In loop: topic is fourth
In subroutine: topic is fourth

Can anyone explain this?

--

Web: http://www.{*filter*}com.net/~rnewman/home.html



Sat, 11 Sep 1999 03:00:00 GMT  
 global my() variable used in foreach() loop loses its value


|I am using a global variable, declared my() at the top level, as
|the loop control variable in a "foreach" loop.
|Instead of getting the expected value of the variable, it instead
|finds the variable to be empty.  Can anyone explain this?

Heavy sigh.

Yes, I can explain it, as can the perl manual pages, as can any perl
book worth reading, as can the FAQ, as can DejaNews (this has only
been discussed what, 7 or 8 times in the past month?).

Try some local resources before posting far and wide. Besides getting
the answer you want much faster, you'll also probably get some answers
you don't need today but will in the future.

Brian
--
Brian L. Matthews                               Illustration Works, Inc.
        For top quality, stock commercial illustration, visit:
                  http://www.halcyon.com/artstock



Sat, 11 Sep 1999 03:00:00 GMT  
 global my() variable used in foreach() loop loses its value



Ron,

my() variables are not visible to subroutines called from inside the
block they are in.

If what your after is making the script comile under use strict; then
do:

use vars qw(topic);

Then eliminate the my $topic;  line.

regards,
scottwimer

Regards.

Quote:
>Here's a Perl script whose behavior I don't understand at all.

>I am using a global variable, declared my() at the top level, as
>the loop control variable in a "foreach" loop.  Inside the loop,
>I call a subroutine which access the global variable.  Instead
>of getting the expected value of the variable, it instead finds
>the variable to be empty.   Why?

>*****  The perl script ********

>#!/usr/local/bin/perl -w

>use strict;
>my $topic;

>main();

>sub main {


>    print "In loop: topic is $topic\n";
>    subroutine();
>    }
>}

>sub subroutine {
>    print "In subroutine: topic is $topic\n";
>}

>******* The output **********

>In loop: topic is first
>Use of uninitialized value at /tmp/foo.pl line 18.
>In subroutine: topic is
>In loop: topic is second
>Use of uninitialized value at /tmp/foo.pl line 18.
>In subroutine: topic is
>In loop: topic is third
>Use of uninitialized value at /tmp/foo.pl line 18.
>In subroutine: topic is
>In loop: topic is fourth
>Use of uninitialized value at /tmp/foo.pl line 18.
>In subroutine: topic is

>******  end of output *******

>If I remove these two lines:

>  use strict;
>  my $topic;

>the program behaves properly:

>In loop: topic is first
>In subroutine: topic is first
>In loop: topic is second
>In subroutine: topic is second
>In loop: topic is third
>In subroutine: topic is third
>In loop: topic is fourth
>In subroutine: topic is fourth

>Can anyone explain this?

>--

>Web: http://www.{*filter*}com.net/~rnewman/home.html



Sun, 12 Sep 1999 03:00:00 GMT  
 global my() variable used in foreach() loop loses its value



Quote:
>my() variables are not visible to subroutines called from inside the
>block they are in.

My example had a *global* my() variable.  This should be visible
from any subroutine that doesn't declare a local my() variable
of the same name.

This, for example, works fine:

#!/usr/bin/perl

my $string = "Hello world!";

subroutine();

sub subroutine() {
    print "$string\n";

Quote:
}

--

Web: http://www.{*filter*}com.net/~rnewman/home.html


Sun, 12 Sep 1999 03:00:00 GMT  
 global my() variable used in foreach() loop loses its value



Quote:


>|I am using a global variable, declared my() at the top level, as
>|the loop control variable in a "foreach" loop.
>|Instead of getting the expected value of the variable, it instead
>|finds the variable to be empty.  Can anyone explain this?

>Heavy sigh.

>Yes, I can explain it, as can the perl manual pages, as can any perl
>book worth reading, as can the FAQ, as can DejaNews (this has only
>been discussed what, 7 or 8 times in the past month?).

I don't see this discussed in any of these places.  Can you
provide a more specific reference?
--

Web: http://www.{*filter*}com.net/~rnewman/home.html


Sun, 12 Sep 1999 03:00:00 GMT  
 global my() variable used in foreach() loop loses its value

Quote:

> my() variables are not visible to subroutines called from inside the
> block they are in.

Unless, of course, the subroutine is declared within the scope of the my
variable, something like this.

    my $foo;

    sub bar { print "I can see $foo from here.\n" }

    $foo = 'you'; &bar;

(I know, you meant that a my variable is not visible outside of its
scope.) Cheers!

-- Tom Phoenix        http://www.teleport.com/~rootbeer/

Randal Schwartz Case:     http://www.lightlink.com/fors/



Sun, 12 Sep 1999 03:00:00 GMT  
 global my() variable used in foreach() loop loses its value


Quote:





>>|I am using a global variable, declared my() at the top level, as
>>|the loop control variable in a "foreach" loop.
>>|Instead of getting the expected value of the variable, it instead
>>|finds the variable to be empty.  Can anyone explain this?

>>Heavy sigh.

>>Yes, I can explain it, as can the perl manual pages, as can any perl
>>book worth reading, as can the FAQ, as can DejaNews (this has only
>>been discussed what, 7 or 8 times in the past month?).

>I don't see this discussed in any of these places.  Can you
>provide a more specific reference?

even heavier sigh.
The following is copied from the perlsyn manpage:

" If the variable is preceded with the keyword my,
then it is lexically scoped, and is therefore visible only within the
loop. Otherwise, the variable is implicitly local to the loop and
regains its former value upon exiting
the loop. If the variable was previously declared with my, it uses
that variable instead of the global one, but it's still localized to
the loop. (Note that a lexically scoped
variable can cause problems with you have subroutine or format
declarations.) "

---
Yours Sincerely,
                                      ,                    
   () o                              /|   |          |      
   /\     _  _  _    __   _  _        |___|        __|   _  
  /  \|  / |/ |/ |  /  \_/ |/ |       |   |\|   | /  |  |/  
 /(__/|_/  |  |  |_/\__/   |  |_/     |   |/ \_/|/\_/|_/|__/
                                               /|          
                                               \|          
(Simon Hyde)



Sun, 12 Sep 1999 03:00:00 GMT  
 global my() variable used in foreach() loop loses its value

[mail&post]

Quote:





> >|I am using a global variable, declared my() at the top level, as
> >|the loop control variable in a "foreach" loop.
> >|Instead of getting the expected value of the variable, it instead
> >|finds the variable to be empty.  Can anyone explain this?

> >Heavy sigh.

> >Yes, I can explain it, as can the perl manual pages, as can any perl
> >book worth reading, as can the FAQ, as can DejaNews (this has only
> >been discussed what, 7 or 8 times in the past month?).

> I don't see this discussed in any of these places.  Can you
> provide a more specific reference?

$Heavy_Sigh x 2.

1) Open Camel.
2) Flip to index, look up "foreach"
  p631: foreach loops, 24, 100, 536-537
3) p.24...  basic stuff nothing interesting
4) p.100... 2nd paragraph:
  The variable is implicitly local to the loop and regains
  its former value upon exiting the loop.  If the variable
  was previously declared with <B>my</B>, that variable
  instead of the global one is used, but it's still
  localized to the loop.

Specific enough?
You do keep the Camel handy don't you?  If so,
why not?  I could probably give you a 4 step process
that would find the relevant info in the man pages too,
but I think I'll leave that one as an exercise.

Do we really need to give instructions on *basic* searching
and reading skills in this group?

HTH
--

eGames.com, Inc.   http://www.egames.com/
eMarketing, Inc.   http://www.emarket.com/
"It's better to be lucky than good."  -- Elizabeth Bourne



Sun, 12 Sep 1999 03:00:00 GMT  
 global my() variable used in foreach() loop loses its value





|>|I am using a global variable, declared my() at the top level, as
|>|the loop control variable in a "foreach" loop.
|>|Instead of getting the expected value of the variable, it instead
|>|finds the variable to be empty.  Can anyone explain this?
|>Yes, I can explain it, as can the perl manual pages, as can any perl
|>book worth reading, as can the FAQ, as can DejaNews (this has only
|>been discussed what, 7 or 8 times in the past month?).
|I don't see this discussed in any of these places.  Can you
|provide a more specific reference?

From perlsyn:

    The foreach loop iterates over a normal list value and sets the
    variable VAR to be each element of the list in turn. *The variable
    is implicitly local to the loop* and regains its former value upon
    exiting the loop.

(Highlighting mine.)

Brian
--
Brian L. Matthews                               Illustration Works, Inc.
        For top quality, stock commercial illustration, visit:
                  http://www.halcyon.com/artstock



Sun, 12 Sep 1999 03:00:00 GMT  
 global my() variable used in foreach() loop loses its value

[ Posted and mailed. ]

Quote:

> Here's a Perl script whose behavior I don't understand at all.  I am
> using a global variable, declared my() at the top level, as the loop
> control variable in a "foreach" loop.  Inside the loop, I call a
> subroutine which access the global variable.  Instead of getting the
> expected value of the variable, it instead finds the variable to be
> empty.  Why?

[snip]

Quote:
> my $topic;

[snip]

Quote:

>    print "In loop: topic is $topic\n";
>    subroutine();
>     }

Because foreach localizes the value of its loop variable to the loop.  The
$topic seen inside the foreach loop won't have the same value as a $topic
outside the foreach loop.  Your subroutine is using the global $topic
variable rather than the one localized to the loop.

(I'm not very clear on why someone would consider this a FAQ -- it's
actually a fairly subtle point.)

--



Sun, 12 Sep 1999 03:00:00 GMT  
 global my() variable used in foreach() loop loses its value

Quote:

> 4) p.100... 2nd paragraph:
>   The variable is implicitly local to the loop and regains
>   its former value upon exiting the loop.  If the variable
>   was previously declared with <B>my</B>, that variable
>   instead of the global one is used, but it's still
>   localized to the loop.

And if you knew exactly what that meant the first time you read it and how
it interacts with subs called from inside foreach loops, you're a lot
better than the rest of us.

Quote:
> Do we really need to give instructions on *basic* searching and reading
> skills in this group?

Oh, please give me a fscking break.  You think it's obvious on first read
that although the word "localizing" is used in the description of what
happens to foreach loop variables, it's *not* doing the same thing as a
local(), which would make the value of the variable available to called
subs from inside the foreach loop, but rather is lexically scoping the
variable and called subs get a different lexical scope?

Scoping issues involving foreach loops and my/local variables aren't the
trivial FAQ you're making them out to be, and you and a half-dozen other
people on this newsgroup are doing yourselves and Ron a major disservice
by treating him like an idiot for not understanding it the first time.

--



Mon, 13 Sep 1999 03:00:00 GMT  
 global my() variable used in foreach() loop loses its value

: Specific enough?
: You do keep the Camel handy don't you?  If so,
: why not?  I could probably give you a 4 step process
: that would find the relevant info in the man pages too,
: but I think I'll leave that one as an exercise.

Sure.  The Camel book is on a shelf shared by everyone in our
office, including Ron.  IMHO, scoping with my() can be tricky
(definitely non-trivial), and the test example he posted was based
on a larger program that was experiencing larger problems.

: Do we really need to give instructions on *basic* searching
: and reading skills in this group?

We don't need any instructions today, thanks.  Ron *did* receive
*quality* answers from others, so thanks for your tough love, and
please exercise your frustrations on "Tickle-Me-Elmo" in the future,
not on people asking reasonable questions.

--
Nathan V. Patwardhan



Mon, 13 Sep 1999 03:00:00 GMT  
 global my() variable used in foreach() loop loses its value


Quote:

>(I'm not very clear on why someone would consider this a FAQ -- it's
>actually a fairly subtle point.)

Indeed, I always refer to it as a bug.   It's a piece of false optimisation.
Fortunately, in modern perls you can write


which doesn't suffer from the problem.

Mike Guy



Tue, 14 Sep 1999 03:00:00 GMT  
 global my() variable used in foreach() loop loses its value

Quote:

>Here's a Perl script whose behavior I don't understand at all.

Well the problem has to do with closures and variable binding.  When
you declare a function within the scope of a lexical variable (in this
case $topic), it remembers which variable it's pointed at.  Therefore,
in your program, the $topic variable in subroutine() is bound to your
declared $topic variable.  HOWEVER in main, $topic is bound
*locally*.

Yeah, that's confusing, but it's in the manual:

     Foreach Loops

     The foreach loop iterates over a normal list value and sets
     the variable VAR to be each element of the list in turn.
     The variable is implicitly local to the loop and regains its
     former value upon exiting the loop.  If the variable was
     previously declared with my, it uses that variable instead
     of the global one, but it's still localized to the loop.
     This can cause problems if you have subroutine or format
     declarations within that block's scope.

Making the variable a true package global is probably a better idea.
(Even better is passing it as a parameter.)

Hope this helps.

--
Ian Flanigan

BTW, to see the strange binding in action, change your script to:

my $topic = "global";

main();

sub main {

    print "Before loop: topic is $topic\n";

        print "In loop: topic is $topic\n";
        subroutine();
    }
    print "After loop: topic is $topic\n";

Quote:
}

sub subroutine {
    print "In subroutine: topic is $topic\n";
Quote:
}



Sat, 18 Sep 1999 03:00:00 GMT  
 
 [ 14 post ] 

 Relevant Pages 

1. losing global variable value??

2. array value in for loop lost when mainloop happens

3. how do I modify the value in an array within a foreach loop

4. sorting hashes by value rather than by key in a foreach loop

5. my variables in foreach loops

6. foreach loop variable localizing

7. Variable evaluation in foreach / for loops??

8. allowed index variables in foreach loops

9. References in foreach loop variable

10. special variable for foreach loops?

11. Using splice in foreach loop.

12. complex foreach loop with deep hashes (sorted hash slices (using an array for keys))

 

 
Powered by phpBB® Forum Software