Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

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":

  • 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, 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, 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.
  • Log In?

    What's my password?
    Create A New User
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others imbibing at the Monastery: (3)
    As of 2018-03-18 04:18 GMT
    Find Nodes?
      Voting Booth?
      When I think of a mole I think of:

      Results (228 votes). Check out past polls.