Declaring a variable with our effectively creates a package variable (i.e. a typeglob entry) and bequeaths a lexical scope upon the short name symbol. A for() loop aliases it's loop variable, so that our $name loop-variable behaves like a local. That's why declaring $name with our results in $name being undefined after the for() loop run, hence the generated subroutines output an empty $name.

Why does the my-variable version work as expected? - Because the for() loop aliases the my variable as - a my variable. Now, for those the compiler inserts an opcode which clears it after (or before?) every iteration (on ENTER or LEAVE), so that you have a brand new $name (with its own private storage!) each time through the loop.

If you close over a localized our() variable, as per your example, all your generated subs share the same local, which isn't visible outside.

Perl is trying really hard to dwim here, and imho does a good job ;-)

update:

Actually, there's more to it, since the loop variable gets an alias of the list it iterates over. Consider:

my $name; for $name (qw(red blue green yellow orange purple violet)) { no strict 'refs'; # allow symbol table manipulation no warnings 'redefine'; #ignore noise about redefinitions *$name = sub { my $sOutput = "<FONT COLOR='$name'>@_</FONT>"; $name = 'something wacky and wonderful'; #change the value return $sOutput; }; } print "red: ${\(red())}\n"; __END__ Modification of a read-only value attempted at - line 7.

Here the for() iterates over a list of literals, and those are read-only. But! ...

our $name; for $name (qw(red blue green yellow orange purple violet)) { no strict 'refs'; # allow symbol table manipulation no warnings 'redefine'; #ignore noise about redefinitions *$name = sub { my $sOutput = "<FONT COLOR='$name'>@_</FONT>"; $name = 'something wacky and wonderful'; #change the value return $sOutput; }; } print "red: ${\(red())}\n"; __END__ red: <FONT COLOR=''></FONT>

...why? In this case, the sub closes over the localized $name, which is undefined after the loop finished. That's why you get

----- sub used inside loop that defined it ------ trying out something wacky and wonderful: <FONT COLOR='something wacky + and wonderful'></FONT>

inside the last loop - you had modified $colors[0] in the previous loop.


In reply to Re: How do closures and variable scope (my,our,local) interact in perl? by shmem
in thread How do closures and variable scope (my,our,local) interact in perl? by ELISHEVA

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.