"Will you come to Sofia?"

If someone pays me to, sure.

"Dunno if caller is somehow safely overwritable"

It can, Sub::Uplevel does this (and documents the caveats).

"Did you notice that Jesse Luehr's module (thanks for showing, BTW) explicitly warns about using it?"

It was my bug report that led him to add the warning. The issue can be worked around with PadWalker though, and that's what I do in the section of my example commented Fix Parse::Keyword's handling of closed over variables. I use Parse::Keyword in a few projects, and with a bit of care, PadWalker seems to be able to fix this problem every time.

The basic problem can be illustrated with this code sample:

use v5.14; my (@x, @y); for my $i (1..3) { push @x, sub { 1 }; push @y, sub { $i }; } say @x; say @y;

It will produce output something like this:

CODE(0x9c3cce8)CODE(0x9c3cce8)CODE(0x9c3cce8) CODE(0x9c2b228)CODE(0x9c2bd08)CODE(0x9c3c9d8)

You'll notice that @x has the same reference three times, while @y has three different references. This is because at compile-time, when a coderef is encountered, and Perl notices that it closes over a variable, it compiles it into a sort of "proto-coderef". Then when the coderef is hit at run-time (in the example above, the execution of the for loop), Perl sees that it's got a proto-coderef, and fixes up the closed over variables to point to the right data. If the coderef doesn't close over any variables, then it can take the shortcut of reusing the same coderef each time it's encountered at run-time.

Anyway, the parse_* functions in Parse::Keyword essentially only give you a proto-coderef. If this closes over any lexical variables, you need to do the run-time "point to the right data" bit yourself. So that's what I do in the example.

If you comment out the PadWalker lines, you'll get warnings about the variables in $x..$y being undefined, this is because without PadWalker the list generation coderef $list is just a proto-coderef compiled before $x and $y have been given any values.

Anyway, I'm probably boring everybody now. I've just used Parse::Keyword more than most people. Despite its shortcomings, I still think there's life in it.

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

In reply to Re^3: 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.