Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??
Sounds like an interesting problem... If you don't use strict you can probably do the equivilent of importing the var from the main package into all subpackages of main that exist at that point in time. You could probably do this with an INIT block that inspects and modifies the symbol table. This, however, won't work for code that runs at compile-time. It also won't work for packages created at run time.

BEGIN { %main::_shared_vars = ( the_very_global => \$the_very_global ); } INIT { package main; sub _iterate_packages_loop { my($stash,$name,$callback) = @_; $callback->($stash,$name); foreach (keys %{$stash}) { if (/::\z/ and $_ ne "main::") { _iterate_packages_loop($stash->{$_},$name.$_,$callback); } } }; sub _iterate_packages { _iterate_packages_loop(\%::,"main::",shift); } _iterate_packages(sub { $_[1] eq "main::" and return; while (my($k,$v) = each %::_shared_vars) { $_[0]->{$k} = $v; } }); } $the_very_global = "GLOBAL!\n"; print $the_very_global; package bar; print $the_very_global; package bar::foo; print $the_very_global;

Fixing this technique to work with use strict can be done by overriding the strict pragma. One can even override it such that strict works as a source-filter that detects package usage and imports the variables appropriately before the code using them is compiled, so most of the advantage of using strict is not lost. I also use caller so if one does package Foo; use strict; it will still work. use strict; package Foo; (on one line) is not likely to work, however.

BEGIN { %main::_shared_vars = ( the_very_global => \$the_very_global ); } BEGIN { use Filter::Util::Call; use strict; my $_strict_import = \&strict::import; package strict; sub _add_to_stash { my $name = shift; no strict 'refs'; while (my($k,$v) = each %::_shared_vars) { # importing this way makes the variable # be considered "declared" for the purposes # of strict. *{$name."::$k"} = $v; } }; *strict::import = sub { # setup the package we are being called by _add_to_stash(scalar caller); filter_add(sub { my $status; while (($status = filter_read()) > 0) { _add_to_stash($1) while /package\s+([\w:]+)/g; last unless(/package\s*\z/); } return $status; }); goto &$_strict_import; }; }

Note that this code doesn't do very smart parsing of package names. I think that's okay since getting false positives is not really a problem. A combination of these two strategys should work except for compile-time run code that doesn't use strict and run-time generated packages that don't use strict. Note that the strategy used with strict can be applied to any module.

There are probably other ways to do this too. The debugging mechanisms may be able to obtain the necessary information to check for package declarations in files after they are loaded and before they are compiled. Alternately, one could write a source filter that does good parsing of perl (Text::Balanced would be helpful) and find all the package declarations and recode requires, dos, evals, uses etc. into something that would also check for package statements appropriately. (The filter would presumably be setup with the main program and work it's way from there.) This would probably be much, much harder than any of the methods mentioned here, though it would be more effective.

In reply to Re: Can you create *real* global variables? by wog
in thread Can you create *real* global variables? by broquaint

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?

What's my password?
Create A New User
Domain Nodelet?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2023-02-03 20:15 GMT
Find Nodes?
    Voting Booth?
    I prefer not to run the latest version of Perl because:

    Results (29 votes). Check out past polls.