"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

In reply to Re^5: Silencing specific warnings when executing coderef? by tobyink
in thread Silencing specific warnings when executing coderef? by LanX

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.