This is as much for my own understanding and may not be entirely correct for Perl (I hope so though).

The function &foo has "free variables" (e.g., variables used within the function body that are NOT declared within the function body). This means that Perl has to go outside the scope of the function to try and provide values for them.

The first place it tries is the scope at which the function was called. Update: that's actually not true. It first tries the scope above the function definition, and then the scope above that it until it finds a declaration or stops at the global scope. In the original code it just so happens the scope at which it finds the declarations is the same as where the function is called - see the supplemental example. Now, you might think that as you declare $foo in front of the function call it should have a value of 1 (it is in the same scope after all). However within the same scope of the first $foo declaration there is a second $foo declaration. The second declaration effectively "masks" the first. Perl doesn't like having two declarations in the same scope so chooses the last one it finds as the one to use. And as this happens to be after the function call, the values aren't initialised when &foo is called.

I'm not sure what actually happens behind the scenes i.e. what does "mask" really mean. Does the second declaration actually overwrite the first? Or is the second declaration always found and used before the first?

What's the truth monks?

Supplemental Example

#!/usr/bin/perl use strict; use warnings; my ($foo, $berries) = (89,90); foo(); { my $foo = 89; sub foo { print "$foo, $berries\n"; }; };

Results in:

,90

When sub foo is compiled it can't find a declaration for $foo so checks the parent scope. It finds it at the line "my $foo = 89". At this point Perl binds the varible $foo to a memory location but doesn't set it's value i.e., it just does the declaration not the initialisation. Further this binding is stored with the function sub $foo (note: this is a closure - the free variable $foo in sub foo gets bound (or closed) in the parent scope and permanently attached to the function).

So, even though in the global context $foo is set before the sub foo call, it doesn't matter because sub foo has it's own binding for $foo which hasn't yet been initialised.


In reply to Re: What is it I don't understand about perl scoping? by mattford63
in thread What is it I don't understand about perl scoping? by brycen

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.