Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

Re: How to safely use $_ in a library function?

by vsespb (Chaplain)
on Sep 17, 2013 at 12:26 UTC ( #1054426=note: print w/replies, xml ) Need Help??

in reply to How to safely use $_ in a library function?

Localize it using "local":
local $_;

Replies are listed 'Best First'.
Re^2: How to safely use $_ in a library function?
by Athanasius (Chancellor) on Sep 17, 2013 at 13:02 UTC

    If I understand the OP’s question correctly, the programme’s structure is something like this:

    #! perl use strict; use warnings; for (qw(literal1 literal2 literal3)) { print "$_\n"; foo('wilma'); } sub foo { $_ = 'fred'; goto &bar; } sub bar { my ($name) = @_; print "foo --> name = $name, \$_ = $_\n"; }

    Unfortunately, changing the line $_ = 'fred'; to local $_ = 'fred'; doesn’t work: it does fix the syntax error, but within sub bar $_ is still literal1, literal2, and literal3 on successive iterations of the for loop. From the documentation for goto (underlining added):

    The goto-&NAME form ... exits the current subroutine (losing any changes set by local()) and immediately calls in its place the named subroutine using the current value of @_.

    The problem is that on each iteration of the for loop, global $_ is made an alias of the next item in the list. When that argument is a literal, this makes global $_ readonly, and that effect is undone only when that loop iteration completes. There doesn’t appear to be any way to undo this effect. :-(

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      "There doesn’t appear to be any way to undo this effect. :-("

      sub foo { Internals::SvREADONLY($_, 0); $_ = 'fred'; goto &bar; }

      The intentionally-undocumented Internals package is part of Perl core (so much so that you don't even need to use it - it's completely internal, like parts of utf8 are) and has nothing much to do with the Internals module on CPAN.

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

        Sounds good; but, if I add

        Internals::SvREADONLY($_, 0);

        to the code I gave above, immediately before the line $_ = 'fred';, I still get:

        1:03 >perl literal1 Modification of a read-only value attempted at line 26. 1:03 >perl -v This is perl 5, version 18, subversion 1 (v5.18.1) built for MSWin32-x +86-multi-thread-64int ...

        Also, where and how can I learn about a feature that is “intentionally-undocumented”? (This is a serious question!)

        Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Indeed, you're right, seems this does not work with goto.
        It fails on the assignment to $_ before the goto. The problem is there is no way to save off $_ and re-use it, making the central register, in perl, frozen/useless. Seems like a crack in the design -- I *rarely* got the message though I've reused that Vars code through many modules over a period of ~3 years.

        As much as anything, not running into it is a reflection of perl-programming style -- i.e. if one rarely, if ever, uses constants hard-coded in the text of the 'for' loop (I almost always use for with an array or such -- even if it is an array of constants -- which doesn't hit this problem).

        To answer the question of what happens if you call "for" in the target of the "goto", it overrides the global usage within the scope of the "for", then restores it. So the language *does* have "inherent" methods to do this, just, apparently, not explicit.

        One reason (among others,) for splitting the code was to have most of the code parsed at compile time and leave as little parsing to runtime as possible. Compare that to the alternative where the entire "main sub" was in-lined in the "eval". Then, not only could I probably get around it by using "for" as a means to assign to "$_", (i.e. for ([$sav, et other vals]) { overriden value of "$_" active here; set to be ptr-to the indirect array }), but I wouldn't need to use it in the first place. *ARG* (hitting head against wall)...

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1054426]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (6)
As of 2017-10-24 12:00 GMT
Find Nodes?
    Voting Booth?
    My fridge is mostly full of:

    Results (289 votes). Check out past polls.