Question

I have a directory structure that looks like:

Foo::Bar::Baz::1 Foo::Bar::Baz::2 etc

Can I list the packages from something like:

use Foo::Bar::Baz;

Thanks!

Edit: Made it more clear what the modules are.

Was it helpful?

Solution

Just to be clear, are you looking at random packages in random Perl code?

Or for Perl modules, e.g. "a/b/c/d1.pm" with module "a::b::c::d1"?

In either case, you can not use a single "use" statement to load them all.

What you need to do is to find all the appropriate files, using either glob or File::Find.

In the first case (modules), you can then load them either by require-ing each file, OR by converting filename into module name (s#/#::#g; s#\.pm$##;) and calling use on each module individually.

As far as actual packages nested in random Perl files, those packages can be:

  • Listed by grepping each file (again, found via glob or File::Find) for /^package (.*);/

  • Actually loaded by executing require $file for each file.

    In this case, please note that the package name for each of those packages in a/b/c/1.pl will NOT need to be related to "a::b::c" - e.g. they CAN be named by the file author "p1", "a::p1" or "a::b::c::p1_something".

OTHER TIPS

If you want to load all modules in your include path with a certain prefix (e.g. everything under a::b::c, you can use Module::Find.

For example:

use Module::Find 'useall';

my @loaded = useall 'Foo::Bar::Baz';  # loads everything under Foo::Bar::Baz

This depends on your @INC path being set up with the necessary directories, so do any required manipulation (e.g. with use lib) first.

Normally a script such as a/b/c.pl won't have a namespace other than main. Perhaps you are thinking of discovering modules with names such as a/b/c.pm (which is a bad name, since lower-cased package names are generally reserved for Perl internals).

However, given a directory path, you can look for potential Perl modules using File::Find:

use strict;
use warnings;
use File::Find;
use Data::Dumper;

my @modules;
sub wanted
{
    push @modules, $_ if m/\.pm$/
}
find(\&wanted, 'A/B');

print "possible modules found:\n";
print Dumper(\@modules)'

This might be overkill, but you can inspect the symbol table before and after loading the module and see what changed:

use strict; use warnings;
my %original = map { $_ => 1 } get_namespaces("::");
require Inline;
print "New namespaces since 'require Inline' call are:\n";
my @new_namespaces = sort grep !defined $original{$_}, get_namespaces("::");
foreach my $new_namespace (@new_namespaces) {
  print "\t$new_namespace\n";
}

sub get_namespaces {
  # recursively inspect symbol table for known namespaces
  my $pkg = shift;
  my @namespace = ();
  my %s = eval "%" . $pkg;
  foreach my $key (grep /::$/, keys %s) {
    next if $key eq "main::";
    push @namespace, "$pkg$key", get_namespaces("$pkg$key");
  }
  return @namespace;
}

New namespaces since 'require Inline' call are:
        ::AutoLoader::
        ::Config::
        ::Digest::
        ::Digest::MD5::
        ::Dos::
        ::EPOC::
        ::Exporter::
        ::Exporter::Heavy::
        ::File::
        ::File::Spec::
        ::File::Spec::Cygwin::
        ::File::Spec::Unix::
        ::File::Spec::Win32::
        ::Inline::Files::
        ::Inline::denter::
        ::Scalar::
        ::Scalar::Util::
        ::Socket::
        ::VMS::
        ::VMS::Filespec::
        ::XSLoader::
        ::vars::
        ::warnings::register::
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top