I was specifically interested in why the particular corner I've backed myself into doesn't work.
{ my $foo = 1; sub level : lvalue {$foo} } print level(); { local level() = 2; print level(); } print level(); __END__

Because of my - it's a closure - and, as stated in perlsub

A "local" is simply a modifier on an lvalue expression.

No matter whether you localize the lvalue expression successfully or not, it is not the variable the lvalue sub operates on which is localized. An lvalue sub results in an lvalue upon which the operation in question is performed at subroutine return, and on the left-hand-side of the lvalue sub call you find the result of that operation. So, I guess you are effectively localizing the subroutine's return value, which isn't what you expected.

In your code above, $foo is a lexically scoped scalar, and your subroutine is a "closure" - it closes over the scalar, which furthermore it isn't visible anywhere but in that scope, and as such can't be localized. Were you successfully operating with local upon that lexical variable, perl would have died with

Can't localize lexical variable $foo at __FILE__ line __LINE__.

Remember that my is a compile time directive, while local is runtime (see my/local, space/time (was: Re: The difference between my and local)).

To localize a subroutine proper, you have to assign a coderef to its typeglob (*foo)

{ local *foo = sub : lvalue { print "wuff: $foo\n"; $foo }; }

to make the localization effective (I guess it is optimized away otherwise, but I haven't checked that).

Try to work out what is happening here:

$\ = "\n"; $foo = 3; sub foo :lvalue { $foo } { local *foo = sub :lvalue { $foo *= 1.25; $foo; }; { local $foo; print '1: ',(foo() = 4); print '2: ',(foo() *= 4); foo() = 2; local *foo = sub :lvalue { local $foo = $foo * 1.25; $foo; }; print '3: ',(foo() *= 4); } local $foo = 4; print '4: ',(foo() /= 2); print '5: ',foo(); } print '6: ',foo(); __END__ 1: 4 2: 20 3: 10 4: 2.5 5: 3.125 6: 3

All that said, an attempt to localize an lvalue sub with

local foo() = 2;

should result at least in a warning as

Useless localizing of a subroutine return value

or the like.

--shmem

_($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                              /\_¯/(q    /
----------------------------  \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

In reply to Re^3: Localize lvalue subroutine. by shmem
in thread Localize lvalue subroutine. by shanna

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.