in reply to Use and Require - making an informed choice.

The speed argument cuts both ways: Loading modules just in time can cause unexpected delays long after the start of the program.

You also seem to focus on "the module's" need (suggesting requisites for the code to run) rather than more general quality aspects (like maintainability benefits through isolation of dependencies).

To summarize, I agree with your habits but would make the necessity of conditional loading the distinctive question. And even if conditional loading is called for, like in your PDA example, I would try hard not to sprinkle "requires" all over my code but isolate that again, perhaps in a meta module.

One exception to this is that I have sometimes followed suit with module authors not using "Carp" up front. It might be time to reconsider that, however.

  • Comment on Re: Use and Require - making an informed choice.

Replies are listed 'Best First'.
Re^2: Use and Require - making an informed choice.
by g0n (Priest) on Jan 30, 2006 at 15:17 UTC
    The meta module is an interesting idea - some mechanism for loading & keeping a list of potentially required modules. Perhaps something like this:

    package Foo; use strict; use warnings; my $foo = Foo->new; $foo->rarelyusedfunction; Foo::CodeLoader->new->list(); sub new { return bless \{},shift; } sub commonlyusedfunction { # do stuff } sub rarelyusedfunction { my $self = shift; my $cl = Foo::CodeLoader->new(); $cl->load('DDS'); my $dds = Data::Dump::Streamer->new; $dds->Dump($self)->Out(); } package Foo::CodeLoader; sub new { my $class = shift; my %modules = ( DDS => 'Data::Dump::Streamer' + ); return bless \%modules,$class; } sub load { my $self = shift; my $param = shift; eval "require $self->{$param}"; } sub list { my $self = shift; for (values %{$self}) { print "$_\n"; } } 1;

    Although I'm always slightly uncomfortable with eval require

    --------------------------------------------------------------

    "If there is such a phenomenon as absolute evil, it consists in treating another human being as a thing."

    John Brunner, "The Shockwave Rider".

        Thanks, I hadn't come across autouse before, and it would certainly solve the problem of scattering requires through ones code to have:

        use autouse 'This::Module'; use autouse 'That::Module';

        At the top of the code. Interestingly though, autouse fails in this particular instance where my quick (and perhaps OO centric) kludge up didn't, because DDS implements an import method:

        autoused module has unique import() method at autouse.pl line 5

        with the following code:

        use strict; use warnings; use autouse 'Data::Dump::Streamer'=>qw(Dump); use autouse 'No::Such::Module'; print "foo\n"; my %hash = ( 1=>'one', 2=>'two', 3=>'three' ); Dump(%hash); my $dds = Data::Dump::Streamer->new; $dds->Dump(%hash)->Out();

        Note: I'd tried both OO & non OO interface, hence the inclusion of two calls to Dump - with the Dump(%hash); line commented out it fails with:

        Can't locate object method "new" via package "Data::Dump::Streamer" (p +erhaps you forgot to load "Data::Dump::Streamer"?) at autouse.pl line + 15.

        --------------------------------------------------------------

        "If there is such a phenomenon as absolute evil, it consists in treating another human being as a thing."

        John Brunner, "The Shockwave Rider".

      The meta module is an interesting idea - some mechanism for loading & keeping a list of potentially required modules.

      That kind of thing -- lazy importing/on-demand functions -- is on my TODO list for ToolSet. If there's a lot of demand for it, I'd be willing to bump it up on my "get around to it" list. I was thinking of exporting a stub function that, if called, would require the real module if it hadn't been loaded already and from then on just directly goto the real function whenever called.

      -xdg

      Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      A minor comment on the call to DDS:

      sub rarelyusedfunction { my $self = shift; my $cl = Foo::CodeLoader->new(); $cl->load('DDS'); my $dds = Data::Dump::Streamer->new; $dds->Dump($self)->Out(); }

      I would write that as follows:

      sub rarelyusedfunction { my $self = shift; if ( eval { require Data::Dump::Streamer; 1 } ) { return scalar Data::Dump::Streamer::Dump($self)->Out(); } else { warn "**DANGER** Falling back to Data::Dumper as DDS" . " isn't available"; require Data::Dumper; return Data::Dumper::Dumper($self) } }

      The scalar there is useful, as Out() behaves differently in list and scalar context (something that was probably a mistake in hindsight and which might change in the next release, I've been putting serious consideration into changing the interface somewhat in version 2).

      I've never bothered with any Autouse stuff personally. The pattern

      if ( eval { require Foo; 1 } ) { .. } else { ... }

      is simple enough I think.

      ---
      $world=~s/war/peace/g