Not loading unneeded modules with use strict? 
Author Message
 Not loading unneeded modules with use strict?

OK, I've written a neat little module of my own (Unigraph) which forms an
abstract interface to various graphics-producing CPAN modules.  In particular,
Unigraph sits in front of GD and PDF::API2 and lets me create *either* a GD
or a PDF graph with identical calls, the only difference being in a parameter
to the Unigraph->new() constructor that tells it which implementation to use.

It's way cool, and lets me write one program that can produce many different
types of graphs.  The problem is, at the top of my Unigraph module I say:

   use strict;
   use GD;
   use PDF::API2;

and the time penalty for loading *both* GD and PDF::API2 (when I only needed
one) is appreciable.

Now I've read chapter 12 of the _Perl Cookbook_ and they tell me how to
replace "use" with "require" and "import", or to wrap the "use" in an "eval",
to avoid loading unneeded modules.  But if I do that, I have to turn off
the "use strict", and I really really like keeping "use strict" in my code
even after it leaves development.

Is there some trick, maybe new with Perl 5.6 or 5.8, which gives
me the best of both worlds, the ability to keep "use strict" while
not loading unneeded modules?

Tim.



Wed, 15 Jun 2005 23:59:30 GMT  
 Not loading unneeded modules with use strict?

Quote:
> OK, I've written a neat little module of my own (Unigraph) which forms an
> abstract interface to various graphics-producing CPAN modules.  In particular,
> Unigraph sits in front of GD and PDF::API2 and lets me create *either* a GD
> or a PDF graph with identical calls, the only difference being in a parameter
> to the Unigraph->new() constructor that tells it which implementation to use.

> It's way cool, and lets me write one program that can produce many different
> types of graphs.  The problem is, at the top of my Unigraph module I say:

>    use strict;
>    use GD;
>    use PDF::API2;

> and the time penalty for loading *both* GD and PDF::API2 (when I only needed
> one) is appreciable.

> Now I've read chapter 12 of the _Perl Cookbook_ and they tell me how to
> replace "use" with "require" and "import", or to wrap the "use" in an "eval",
> to avoid loading unneeded modules.  But if I do that, I have to turn off
> the "use strict",

Why, exactly?  I don't see how these techniques violate strictures.

Quote:
>                   and I really really like keeping "use strict" in my code
> even after it leaves development.

Right you are.

Quote:
> Is there some trick, maybe new with Perl 5.6 or 5.8, which gives
> me the best of both worlds, the ability to keep "use strict" while
> not loading unneeded modules?

If you have to break strictures in your program, you can usually limit
the effect to a small block.  Create a bare block if the critical code
isn't already inside one, and then do "no strict 'vars'" (or whatever)
inside the block.  Strictures will still be in place for the rest of
the program.

Anno



Thu, 16 Jun 2005 00:17:23 GMT  
 Not loading unneeded modules with use strict?

: It's way cool, and lets me write one program that can produce many different
: types of graphs.  The problem is, at the top of my Unigraph module I say:
:
:    use strict;
:    use GD;
:    use PDF::API2;
:
: and the time penalty for loading *both* GD and PDF::API2 (when I only needed
: one) is appreciable.
:
: Now I've read chapter 12 of the _Perl Cookbook_ and they tell me how to
: replace "use" with "require" and "import", or to wrap the "use" in an "eval",
: to avoid loading unneeded modules.  But if I do that, I have to turn off
: the "use strict",

Says who?  What does strict gripe about when you do this?



Thu, 16 Jun 2005 00:38:13 GMT  
 Not loading unneeded modules with use strict?

Quote:

> OK, I've written a neat little module of my own (Unigraph) which forms
> an abstract interface to various graphics-producing CPAN modules.  In
> particular, Unigraph sits in front of GD and PDF::API2 and lets me
> create *either* a GD or a PDF graph with identical calls, the only
> difference being in a parameter to the Unigraph->new() constructor
> that tells it which implementation to use.

> It's way cool, and lets me write one program that can produce many
> different types of graphs.  The problem is, at the top of my Unigraph
> module I say:

>    use strict;
>    use GD;
>    use PDF::API2;

> and the time penalty for loading *both* GD and PDF::API2 (when I only
> needed one) is appreciable.

> Now I've read chapter 12 of the _Perl Cookbook_ and they tell me how
> to replace "use" with "require" and "import", or to wrap the "use" in
> an "eval", to avoid loading unneeded modules.
> But if I do that, I have to turn off the "use strict",

Assuming that 'strict' is complaining about your use of barewords, then
this can be fixed in a few ways -- the first, and simplest, is to add
parens... simply change all calls of the form:
   foo;
   bar $arg, $arg, $arg;

Into:
   foo();
   bar( $arg, $arg, $arg );

If the subroutines don't have prototypes, then this is likely to be
best.

The second way is to predeclare all the subs;
   sub subname1; sub subname2; sub subname3; # etc.
This has the benefit that you can leave the body of your code unchanged
(other than having to add require/import into your 'new'), and you can
have prototypes.

The third way is the autouse module:
   use autouse GD => qw(subname1 subname2 subname3);
   use autouse PDF::API2 => qw(subname4 subname5 subname6);

With this, you don't have to make *any* changes to the rest of your code
-- you don't even have to make ->new load up one of the two modules via
require and perform an import, as autouse will do that automatically.

Quote:
> and I really really like keeping "use strict" in my code
> even after it leaves development.

> Is there some trick, maybe new with Perl 5.6 or 5.8, which gives
> me the best of both worlds, the ability to keep "use strict" while
> not loading unneeded modules?

Add parens.

--
$..='(?:(?{local$^C=$^C|'.(1<<$_).'})|)'for+a..4;
$..='(?{print+substr"\n !,$^C,1 if $^C<26})(?!)';
$.=~s'!'haktrsreltanPJ,r  coeueh"';BEGIN{${"\cH"}
|=(1<<21)}""=~$.;qw(Just another Perl hacker,\n);



Thu, 16 Jun 2005 06:50:19 GMT  
 Not loading unneeded modules with use strict?


Wed, 18 Jun 1902 01:00:00 GMT  
 Not loading unneeded modules with use strict?

Quote:

> The third way is the autouse module:
>    use autouse GD => qw(subname1 subname2 subname3);
>    use autouse PDF::API2 => qw(subname4 subname5 subname6);

> With this, you don't have to make *any* changes to the rest of your code
> -- you don't even have to make ->new load up one of the two modules via
> require and perform an import, as autouse will do that automatically.

Thanks, "use autouse" looks very tempting.  One question, though:
Both GD and PDF::API2 have a "new" method.  When I say

  use autouse GD::Image => qw(new);
  use autouse PDF::API2 => qw(new);

it seems that the only "new" I can access is the PDF::API2 one, and
when I explicitly try a "GD::Image->new" or a "PDF::API2->new" I get a

  Can't locate object method "new" via package "GD::Image" (perhaps you
  forgot to load "GD::Image"?) at Unigraph.pm line 7.

I'm assuming that my only problem here is syntax (e.g. "how do I distinguish
between the two autoused "new"'s) but maybe the disconnect is more
fundamental.  I looked at the online docs for "use autouse" as well
as in the Perl Cookbook but they're really very vague about how I can
use them to abstract two classes with identical method names into one
"universal" class, like I want.

Tim.



Thu, 16 Jun 2005 17:42:41 GMT  
 Not loading unneeded modules with use strict?

Quote:


> > The third way is the autouse module:
> >    use autouse GD => qw(subname1 subname2 subname3);
> >    use autouse PDF::API2 => qw(subname4 subname5 subname6);

> > With this, you don't have to make *any* changes to the rest of your
> > code -- you don't even have to make ->new load up one of the two
> > modules via require and perform an import, as autouse will do that
> > automatically.

Hmm.... actually, looking over the docs, this is untrue -- autouse
doesn't work like that.  It's only for imported functions, not for
methods.  (and PackName->new is a package method).

Quote:
> Thanks, "use autouse" looks very tempting.  One question, though:
> Both GD and PDF::API2 have a "new" method.  When I say

>   use autouse GD::Image => qw(new);
>   use autouse PDF::API2 => qw(new);

> it seems that the only "new" I can access is the PDF::API2 one, and
> when I explicitly try a "GD::Image->new" or a "PDF::API2->new" I get a

>   Can't locate object method "new" via package "GD::Image" (perhaps
>   you forgot to load "GD::Image"?) at Unigraph.pm line 7.

> I'm assuming that my only problem here is syntax (e.g. "how do I
> distinguish between the two autoused "new"'s) but maybe the disconnect
> is more fundamental.  I looked at the online docs for "use autouse" as
> well as in the Perl Cookbook but they're really very vague about how I
> can use them to abstract two classes with identical method names into
> one "universal" class, like I want.

I hadn't really thought about your problem enough when I first tried to
answer your problem.  Assuming that everything for using GD::Image and
PDF::API2 is object oriented, then a better solution would probably be
something like:

for my $pack (qw(GD::Image PDF::API2)) {
   (my $file = $pack.".pm") =~ s,::,/,g;
   next if $INC{ $file };
   my $glob = do { no strict 'refs'; \*{$pack."::new"} };
   *$glob = sub {
      undef &$glob;
      require $file;
      goto &{$pack->can("new") or die "$pack can't ->new"};
   };

Quote:
}

If you stick this up top, then GD::Image->new and PDF::API2->new will
automatically load up GD::Image and PDF::API2.

--
$..='(?:(?{local$^C=$^C|'.(1<<$_).'})|)'for+a..4;
$..='(?{print+substr"\n !,$^C,1 if $^C<26})(?!)';
$.=~s'!'haktrsreltanPJ,r  coeueh"';BEGIN{${"\cH"}
|=(1<<21)}""=~$.;qw(Just another Perl hacker,\n);



Thu, 16 Jun 2005 22:20:45 GMT  
 Not loading unneeded modules with use strict?

Quote:


> > I'm assuming that my only problem here is syntax (e.g. "how do I
> > distinguish between the two autoused "new"'s) but maybe the disconnect
> > is more fundamental.  I looked at the online docs for "use autouse" as
> > well as in the Perl Cookbook but they're really very vague about how I
> > can use them to abstract two classes with identical method names into
> > one "universal" class, like I want.

> I hadn't really thought about your problem enough when I first tried to
> answer your problem.

That's OK; you came a lot closer than the other responders!

Quote:
>  Assuming that everything for using GD::Image and
> PDF::API2 is object oriented, then a better solution would probably be
> something like:

> for my $pack (qw(GD::Image PDF::API2)) {
>    (my $file = $pack.".pm") =~ s,::,/,g;
>    next if $INC{ $file };
>    my $glob = do { no strict 'refs'; \*{$pack."::new"} };
>    *$glob = sub {
>       undef &$glob;
>       require $file;
>       goto &{$pack->can("new") or die "$pack can't ->new"};
>    };
> }

> If you stick this up top, then GD::Image->new and PDF::API2->new will
> automatically load up GD::Image and PDF::API2.

Cool.  It looks like this creates a dummy entry in the symbol table for all
the "new" methods that I list, does the "require" when I actually
invoke each specific new, and destroys the dummy after it's actually loaded.

Under Perl 5.8.0, I had to comment out the "undef &$glob;" line because
it gave me the run-time message

  Can't undef active subroutine at Uni.pm line 10.

It *seems* to be enough to just replace the name of the subroutine when
the require takes place.  My understanding is that if the dummy subroutine
goes out of scope (is no longer referenced and is not being executed)
it gets destroyed, so I'm not sure that the "undef &$glob;" was needed.

Otherwise, the concept seems to work.  It's a neat concept, because if
everything after the "->new" is accessed via object-oriented methods, then
the only thing I'll ever have to name at the top is the "->new".

Of course, not all modules are purely OO, but I've learned enough that I
think I can deal with those now!  (Possibly there will be some ugly stuff
with any BEGIN blocks, etc...)

Thank you!

Tim.



Fri, 17 Jun 2005 17:07:11 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. Can't load module Tk, dynamic loading not available in this p

2. use strict refs not so strict?

3. Undefined, module not loading?, Bulkmail

4. correct references to module functions when using strict?

5. perlcc: not loading modules

6. HELP: Modules load as root, not user.

7. Using strict in a module ?

8. load frequently used modules from one include file

9. SRC: Devel::Loaded.pm - post-execution dump of loaded modules

10. Module loading error: Apache can't load Apache::Server

11. static load of dyn-load modules

12. Using modules or not?

 

 
Powered by phpBB® Forum Software