http://qs321.pair.com?node_id=649178

bdimych has asked for the wisdom of the Perl Monks concerning the following question:

I do not want "use y" into z.pm
~>cat x.pl use y; use z; z_sub(); ~>cat y.pm package y; sub global_sub { print "global_sub working!" } 1 ~>cat z.pm package z; use Exporter 'import'; our @EXPORT = qw(z_sub); sub z_sub { global_sub(); } 1 ~>perl x.pl Undefined subroutine &z::global_sub called at z.pm line 5.
I think, simplest way is to declare global_sub with some blank dummy namespace:
~>cat x.pl use y; use z; z_sub(); ~>cat y.pm package y; sub G::global_sub { print "global_sub working!" } 1 ~>cat z.pm package z; use Exporter 'import'; our @EXPORT = qw(z_sub); sub z_sub { G::global_sub(); } 1 ~> perl x.pl global_sub working!
but I just do not like "G::"! Please help

Replies are listed 'Best First'.
Re: How to declare globally visible subroutine like built-in ones ? Is it possible?
by shmem (Chancellor) on Nov 06, 2007 at 12:44 UTC
    You could
    *::global_sub = \&global_sub;

    and qualify your global subs with the empty package, on invocation:

    $result = ::global_sub($args);

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Thanks, Anonymous Monk, shmem It works, but ugly annoying evil :: remains! :)

      Anonymous Monk No, overhead is not the problem. I have not exact instructions, what I've asked about. I may change any code of the project and even G:: is, in general, ok.
      My question is exactly subject, it is just interestingly to me.

Re: How to declare globally visible subroutine like built-in ones ? Is it possible?
by Anonymous Monk on Nov 06, 2007 at 11:42 UTC

    Are you sure you don't wan't use y; or require y; in z.pm?? This means that your depending on y.pm being loaded somewhere else, which is a pretty big trap for someone, yourself probably, debugging latter.

    In any case, if you only want to use it from within package z, you could do this in y.pm

    sub z::global_sub { print "global_sub working!"; }
    If you don't like "G::global_sub", how about "::global_sub"? Think of '::' as a sigil (or twigil) for global. And as long as you use package declartions everywhere, you won't stomp on anyone elses namespace.
      >Are you sure you don't wan't use y; or require y; in z.pm??

      Yes, I've given simplified example. Actually y.pm is a runtime library with many submodules:

      script.pl - "use y";
      y.pm - load many submodules with "subnamespaces", and export many subs to the script.pl
      z.pm - one of submodules

      Perl is Perl, it allows almost all, I suppose it is possible to make my problem in some way...

        If you're looking to avoid the overhead of loading all the submodules in y.pm but still having access to the code of y.pm proper, you could consider refactoring so that the big load/export is visible as y, but the actual code of y.pm occurs in y/actual.pm

        Then in y.pm

        require y::actual; push @ISA, 'y::actual';

        This would leave y.pm with the same public interface, but give you the option of a leaner y::actual or y::tiny or y::whatever available. This will only work of course, if the code in y.pm doesn't itself depend on those submodules.

        You could also look at autoloading and/or custom import subroutines

        If you're just woried about namespace polution, s/use/require/