in reply to Re^9: Accessing lexicals in other scopes dynamically by name
in thread Accessing lexicals in other scopes dynamically by name

I am sorry, I think I expained what I meant rather poorly and we are probably not talking about the same things.

I was just refering to an implementation of Scheme in Scheme in which for every lexical scope a data-structure (called an "environment") was created which basically is a symbol-table. This symbol-tables also point back to the symbol-table of the enclosing lexical scope and this link is then followed when one has to look up a symbol which is not found in the current scope.

This symbol-table is always needed by the interpreter to keep the variable-bindings - regardless of whether there are closures or not - and can be used to implement closures.

In such a scenarion a closure would simply refer to an already existing data-structure containing all variable-bindings - so the number of variables is irrelevant for the cost of creating a closure and >>all<< variable bindings are available to the closure.

Naively I had assumed that this was a standard technique and Perl would do the same thing, which is why I was surprised when you demonstrated that there are lexial variables that are defined when the closure is created, yet are not accessible to it because Perl could not "see" that the closure would reference them indirectly.

  • Comment on Re^10: Accessing lexicals in other scopes dynamically by name

Replies are listed 'Best First'.
Re^11: Accessing lexicals in other scopes dynamically by name
by ikegami (Patriarch) on Jul 31, 2010 at 18:49 UTC

    Perl functions have pads, but they are re-used, not recreated every call.

    In such a scenarion a closure would simply refer to an already existing data-structure containing all variable-bindings - so the number of variables is irrelevant for the cost of creating a closure and >>all<< variable bindings are available to the closure

    Again, that would make closures faster at the expense of making every function call slower.

    You seem to be implying one can avoid creating some variables, but all you're doing them is creating them sooner and when they're not needed.

      I am still not sure we talk about the same things (and hey - it's really not all that important), but here is what I don't understand:

      What happens in the interpreter when a statement such as "my $a=1;" is encountered?

      I suppose the "binding" of the name "$a" to the value "1" is recorded in some data-structure (whatever that data-structure is called in the internals of Perl).

      Then whenever $a is referenced this data-structure is examined.

      When another statement "my $b=2" is encountered I suppose this new binding of the name "$b" to the value "2" is also recorded in a data-structure - and I would expect it to be the same data-structure - the data-structure that holds all lexial variables for a given lexial scope.

      Now when a closure is created it needs to "remember" the lexial variables in scope and this could easily achieved by giving the data-structure that describes a closure simply a pointer (or a reference or whatever) to the data-strcuture that holds the variable-bindinds (and holding all of them).

      This is what I had expected (from 10.000 feet) the Perl-interpreter to do.

      But - as you pointed out it - that is not how it works.

      So how does it actually work?

      Can anyone explain at a very high level how lexical variables and closures are implemented in the Perl-internals?

        I suppose the "binding" of the name "$a" to the value "1" is recorded in some data-structure (whatever that data-structure is called in the internals of Perl).

        You're mixing compile-time events with run-time events.

        The slot is added to the pad ("the data structure") at compile time (i.e. once per "my" in the code).

        The assignment of "1" to the scalar occurs at run-time (i.e. once every time "my" is evaluated).

        Under your model, the following code would add 8 entries to "the data structure" over time.

        for (1..4) { my $a = 1; my $b = 2; }

        Perl only does that twice, at compile time.

        (Independently, there's an optimisation in place that makes it so only two scalars are created in total. They are cleared and reused rather than freed.)

        What happens in the interpreter when a statement such as "my $a=1;" is encountered?

        At compile time, it declares the variable, i.e. adds a slot to the function's pad for $b.

        At run-time, it assigns 1 to the variable after placing an instruction on the stack to clear (or replace) the variable on scope exit (the aformentioned optimisation).