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

I am moving a bunch of code out of the main namespace and into a new package/module. The problem is all the old code tries to directly reference subroutines and some global vars (that are in the main namespace) directly and it doesn't work now that I've moved them out of that namespace and into a new one. If I go to each sub reference and change it from mySub() to &::mySub() and go to each global var from the main namespace and change refs to it from $myMainGlobal to $::myMainGlobal it works fine. I was wondering if there was an easy way to make Perl first check the current namespace for a sub or var name but if not found as defined to then check the main namespace too? Or is my only choice in this situation to modify all the references to have a :: prefix?
Thanks.
  • Comment on Checking more than just the current namespace for sub and var definitions

Replies are listed 'Best First'.
Re: Checking more than just the current namespace for sub and var definitions
by ELISHEVA (Prior) on Sep 27, 2009 at 04:29 UTC

    I don't know how you would do that for variables, but for subroutines, you could try AUTOLOAD. However, I wouldn't recommend it. If you are trying to migrate your code from the main namespace to more specialized namespaces, those "method not found" errors are your friends - they tell you that you have missed a dependency that maybe should be moved as well to the new namespace.

    To be honest, I'm not sure I've understood your goal. You've moved code from the main namespace to more specialized namespaces, but you still want all of your variables and subs to refer to the main namespace? That doesn't make much sense to me. The normal reason for moving code and variables into namespaces is to provide better encapsulation.

    Better encapsulation would mean studying the code to find out what routines call what other routines and variables. Then if a variable $X is only used by sub A(), sub B(), and sub C(), all of which are in namespace Foo, you would move $X to Foo. If sub Y() was also only used by routines in Foo, you would move sub Y() to the Foo namespace as well.

    Perhaps you are trying to eventually transition your code to namespaces, and don't want everything to break in the short term? If so, it is better to do these changes incrementally and bottom up. Move one subroutine at a time over to the new namespace. Study its code and make a conscious decision about the namespace for each variable and subroutine consumed by the one you just moved. Does it belong in the new namespace? main? some third namespace?

    Start with a low level routine that is essential private to the mega routine that you eventually want to move. When you have moved several routines and variables over to the new namespace, and the mega subroutine has only a handful of dependencies left in "main", then and only then, move the mega routine.

    Also be aware that when you move routines to a new namespace, all of the consumers of the moved routine will now need to change their calls to refer to the new namespace (which won't be main). If there are a lot of routines calling X() or you don't have a good way of tracking down all of the callers of X(), you may want to think twice about moving sub X() to a new namespace.

    Best, beth

Re: Checking more than just the current namespace for sub and var definitions
by moritz (Cardinal) on Sep 27, 2009 at 09:12 UTC

    A common solution is to first move subs with no or little dependencies to a module, and then use that module both from the main script and from the other modules you are going to create.

    The solution for variables is to rely less on implicitly shared state, but rather pass that information as arguments to the subroutines, or encapsulate it into objects.

    Perl 6 - links to (nearly) everything that is Perl 6.
Re: Checking more than just the current namespace for sub and var definitions
by Khen1950fx (Canon) on Sep 27, 2009 at 09:03 UTC
    I recently ran up against the same problem. Unfortunately, I couldn't find any easy way to to solve the problem, so I've been using Sub::Mutate. It's basically for examination and modification of subroutines. Try this script to get started. I left out the mutation methods. You can add them when you think that you're ready.

    #!/usr/bin/perl use strict; use warnings; use Sub::Mutate qw( sub_body_type sub_closure_role sub_is_lvalue sub_is_constant sub_is_method sub_is_debuggable sub_prototype ); my $sub = \&finddeps; my $type_body = sub_body_type($sub); my $type_closure = sub_closure_role($sub); my $type_is_lvalue = sub_is_lvalue($sub); my $type_is_constant = sub_is_constant($sub); my $type_is_method = sub_is_method($sub); my $type_is_debuggable = sub_is_debuggable($sub); my $type_prototype = sub_prototype($sub); print "$type_body, $type_closure, $type_is_lvalue, $type_is_constant, $type_is_debuggable, $type_prototype\n"; sub finddeps { use CPAN::FindDependencies; my @dependencies = CPAN::FindDependencies::finddeps(); foreach my $dep (@dependencies) { print ' ' x $dep->depth(); print $dep->name().' ('.$dep->distribution().")\n"; } }
Re: Checking more than just the current namespace for sub and var definitions
by Anonymous Monk on Sep 27, 2009 at 05:35 UTC
    Or is my only choice in this situation to modify all the references to have a :: prefix?

    No, you should switch paradigms, switch to object oriented programming.

Re: Checking more than just the current namespace for sub and var definitions
by CountZero (Bishop) on Sep 27, 2009 at 16:29 UTC
    If you are moving your sub-routines and variables to their own packages and modules, then --at least in the short run-- you should think of exporting them back to the namespace you are in when useing that module. Have a look at Exporter to see what I mean.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James