Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

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

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


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

That's widely used pattern (1):

package MyLib; our $MyLibrarysGlobalCallStackInformation; sub myfunc1 { local $MyLibrarysGlobalCallStackInformation = $somedata; myfunc2(); } sub myfunc2 { # use $MyLibrarysGlobalCallStackInformation here }
Another approach (2) would be pass data directly to functions.
package MyLib; sub myfunc1 { myfunc2($somedata); } sub myfunc2 { my ($somedata) = @_; # use $somedata here }
Always use (2), if possible.
Usually you need (1) when writing some kind of fancy DSL.
For you case "goto &sub", you probably can hack something like this:
package MyLib; sub myfunc1 { my (@args) = @_; return myfunc2(@args, $somedata); #instead of goto &myfunc2 } sub myfunc2 { my ($arg1, $arg2, $arg3, $somedata) = @_; if (defined $somedata) { .. # we got there from myfunc1 } }


Comment on Re: How to safely use $_ in a library function?
Select or Download Code
Replies are listed 'Best First'.
Re^2: How to safely use $_ in a library function?
by perl-diddler (Hermit) on Sep 17, 2013 at 15:18 UTC
    FWIW, saving, restoring and not interfering w/context is important, as is speed, though perhaps the call/return vs. goto isn't that much difference given other functionality, it does change the call stack and make detecting context issues in main function more complicated.

    Some of the code:

    ... use warnings; use warnings FATAL => qw(redefine closure); use Types; use Scalar::Util qw(looks_like_number); use constant CLASS => __PACKAGE__; use Want; sub _Var ($$$;$) :lvalue { # Wrkhorse code for manufc +trd Vars my ($__, $p, $vn, $wa)=@$_; # vn=varname our $_=$__; # must not trash '$_ +' my $c = ref $p || $p; my $rfv = ref $p->{$vn}; # rfv=ref(type) of var my $addrof; if ($wa && $wa eq 'α') { $wa=undef, $addrof=1 } my $arg = $_[0]; return $p->{$vn}=want('ASSIGN') if want(qw(LVALUE ASSIGN)); if (@_ && !$addrof) { # arg for "setter" my $rfa = ref $arg; # ref of the arg if ( !defined($p->{$vn}) or !defined $arg ){ # either undef $p->{$vn} = $arg; } elsif ($rfv eq ARRAY) { ## if type(var)==ARRAY, +1 param my ($index, $ap) = (shift, $p->{$vn}); if ($p->{':pusharray'} or ( !looks_like_number($index) || not( (defined $wa) || @_) )) { push @{$p->{$vn}}, ($index); ## convert to "push" return $index; ## return pushed val +ue } else { $p->{$vn}[$index] = $_[0] if @_; return $p->{$vn}[$index]; } } elsif ($rfv eq HASH) { my $subvar = shift; ## 1 var w/hash is is +a key $p->{$vn}{$subvar} = $_[0] if @_; ## another? =>assign +value return $p->{$vn}{$subvar}; } else { if (length $rfv && $rfv ne $rfa ) { ## incompat assignment warn P "Warning: var type redefined from \"%s\" to \"%s\"", $rfv, $rfa; } $p->{$vn} = $_[0]; ## assignment is default } } # how to return results? (belo +w) if ($rfv eq ARRAY ) { if (defined($wa)) { # arrays special $wa? @{$p->{$vn}} : $addrof ? \$p->{$vn} : $p->{$vn}; } } elsif ($rfv eq HASH ) { $p->{$vn} } elsif ($addrof) { return $p->{$vn} } else { return $p->{$vn}; } } sub varname ($) { substr $_[0], (1+rindex $_[0],':') } sub _access_maker { #{{{ my $pkg = shift; #var in $_ { my $proc = '# line ' . __LINE__ . ' "' . __FILE__ . "\"\n" . ' { use warnings;use strict; package '.$pkg.'; sub '.$_.' (;$) :lvalue { my $sav = [$_,shift, Data::Vars::varname((caller 0)[3]), wan +tarray]; our $_=$sav; goto &Data::Vars::_Var}; 1}'; eval $proc; $@ and die "Fatal error in $pkg\::Vars\::_access_maker?: $@\n"; } } ## end sub _access_maker }}}
    The "Types" module is fairly simple and has a bunch of functions to allow some ease-of-use code like:
    sub ARRAY (;*) { my $p = $_[0]; return @_ ? (ref $p && (1+index($p, '::ARRAY')? 1:0) : 'ARRAY' }
    I.e. it allows one to
    my $ptr=[]; say ARRAY if ARRAY $ptr;
    (with a definition for all the types -- which might explain some syntax issues in the _Var sub)

    Given that perl's not re-entrant with it's use of '$_' anyway, I suppose that using some "global var" to pass the name isn't going to be much worse.

    I'm not sure how local would help or work w/goto, though it would help w/they nested call case.

    Given that I pass most of my needed context from the named func to the generic, I likely no longer have a great need to not nest the calls, though conceptually (and historically), more of the the code for '_Var' was in the named function. There has been a fear of losing the caller's context (stuff accessible on call stack as well as 'wantarray' usage), but most of that may already be encapsulated.

    I had hoped that more context saving of $_ went on in perl than does, but that it doesn't, might make my concerns moot. *sigh*.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1054431]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (8)
As of 2015-07-08 00:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (93 votes), past polls