Exporter tells you what not to export:

> Exporting variables is not a good idea. They can change under the hood, provoking horrible effects at-a-distance that are too hard to track and to fix. Trust me: they are not worth it.

The right way is to export the accessors to the variable rather than the variable itself. This makes local useless, so we have to find a different way. For example, we can use Scope::Guard:

package Dsay; use warnings; use strict; use feature qw{ say }; use experimental qw( signatures ); use Scope::Guard qw{ guard }; use Exporter qw{ import }; our @EXPORT = qw( %debug set_darea get_darea dsay ); our %debug; my $d_area = '(default)'; # Not ours anymore! sub set_darea($value) { my $old_value = $d_area; $d_area = $value; return guard { $d_area = $old_value } } sub get_darea() { $d_area } # Etc.
and
sub common_sub { say 'call to common sub (d_area is ', get_darea(), ')'; dsay "debugging output from common_sub"; } sub one { say "call to one:"; my $_scope = set_darea('one'); dsay "debugging output from one"; common_sub; dsay "more debugging output from one"; } sub two { say "call to two:"; my $_scope = set_darea('two'); dsay "debugging output from two"; common_sub; dsay "more debugging output from two"; }
Note that if you don't store the result of set_area to a variable, the module will complain:

Can't create a Scope::Guard in void context

Aside from doing it the right way, you can create the alias to the package variable yourself:

use Dsay; package Dsay; our $d_area; package main;

or

*d_area = *Dsay::d_area;

which can be done by extending Exporter's import:

use Exporter; our @EXPORT = qw( %debug dsay $d_area ); our %debug; our $d_area = "(default)"; sub import { my $caller = caller; no strict 'refs'; *{ $caller . '::d_area' } = *Dsay::d_area; goto &Exporter::import }

Interestingly, using something other than a scalar works the way you wanted.

use Exporter qw{ import }; our @EXPORT = qw( %debug %opt dsay ); our %debug; our %opt = (d_area => "(default)"); sub dsay( @args ) { return unless $debug{ uc $opt{d_area} } || $debug{'ALL'}; my $prefix = $opt{d_area} ne "(default)" ? "DEBUG $opt{d_area}: " : "DEBUG: "; say $prefix, @args; }
and
sub one { say "call to one:"; local $opt{d_area} = "one"; dsay "debugging output from one"; common_sub; dsay "more debugging output from one"; } # Etc.

Update: The reasons for this are unclear to me (maybe local for hash values was implemented later than local for variables, so there are probably some differences in the implementation).

Update 2: Extending the import method added.

Update 3: In fact, what exporter does is quite similar:

*{"${callpkg}::$sym"} = $type eq '&' ? \&{"${pkg}::$sym"} : $type eq '$' ? \${"${pkg}::$sym"} : $type eq '@' ? \@{"${pkg}::$sym"} : $type eq '%' ? \%{"${pkg}::$sym"} : $type eq '*' ? *{"${pkg}::$sym"} : do { require Carp; Carp::croak("Can't export symbol: $type +$sym") };
and if you try the same instead in the redefined import method, it doesn't work either. There's something more than the scalar slot that needs to be aliased, not sure why. The following works, too:
*{ $caller . '::d_area' } = 'Dsay::d_area';

Update 4: In fact, adding the following line after Exporter::Heavy's block seems to fix the behaviour of Exporter without breaking anything I have tried:

*{"${callpkg}::$sym"} = "${pkg}::$sym" if '$' eq $type;

map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

In reply to Re: 'local' for imported variables doesn't work as expected (4 updates) by choroba
in thread 'local' for imported variables doesn't work as expected by muthm

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.