in reply to Re^3: Silencing specific warnings when executing coderef?
in thread Silencing specific warnings when executing coderef?

> If someone pays me to, sure.

I'll send you a postcard! :)

> Anyway, I'm probably boring everybody now.

not me! :)

Also because a week ago I started using exactly these closed_over features of PadWalker and this worries me a little.

what does "when the coderef is hit at run-time" exactly mean?

Lets say

a) I use B::Deparse to deparse and reeval the body of a named sub in a phase before runtime (e.g. CHECK)

b) the function has "normal" closed-over variables, i.e. not depending on run-time variables like from a for-loop.

Do I risk that PadWalker gets it wrong if I transfer the closed-over vars from old to new sub?

Cheers Rolf

( addicted to the Perl Programming Language)

  • Comment on Re^4: Silencing specific warnings when executing coderef?

Replies are listed 'Best First'.
Re^5: Silencing specific warnings when executing coderef?
by tobyink (Canon) on Mar 24, 2014 at 10:42 UTC

    "what does "when the coderef is hit at run-time" exactly mean?"

    There are two important phases that Perl goes through when executing a file: compile-time (a.k.a. BEGIN) and run-time. (Perl actually has a few others like UNITCHECK, CHECK, INIT and END, but I mostly consider those to be subphases of the two big ones.)

    In the compile phase, Perl tokenises and parses the script, turning it into an in-memory optree (what might be called an abstract syntax tree in most programming languages). In the runtime phase, Perl steps through the optree, executing each operation in it.

    So in the compile phase, when Perl sees something like this:

    my $code = sub { $x }; # $x is closed over

    It will compile the sub { $x } into a GV structure in memory; the proto-coderef. The value of $x is not yet known, so the coderef is useless as-is. (But it still needs to be parsed and compiled during this phase because otherwise Perl couldn't determine where the coderef ends, and thus where to resume parsing the code after the coderef. It can't just look ahead for a closing brace because print "}".)

    Later on, at run-time, when it's going through the optree, it has to do an assignment to $x. It evaluates the right-hand side of the assignment, which is a coderef. It notices that the coderef is a proto-coderef, so it clones the proto-coderef and fixes up the closed-over variables.

    It's possible to see this by looking at the coderef's flags using Devel::Peek. Compare the outputs of:

    $ perl -MDevel::Peek -e'my $x; Dump(sub {1})' $ perl -MDevel::Peek -e'my $x; Dump(sub {$x})'

    "Do I risk that PadWalker gets it wrong if I transfer the closed-over vars from old to new sub?"

    Your main problem doing this will be our variables rather than lexicals.

    You may be interested in this StackOverflow question, and also in talking to Graham Knop (HAARG on CPAN) who has been looking at this problem with regards to improving Sub::Quote. He's had some success with our variables, albeit using some very ugly techniques (capturing and parsing the output of Devel::Peek!!), and I believe has managed to get everything to work with no non-core dependencies. His code is here.

    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name