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

Suppose I have a really cool module buried deep in the module tree. Constructing really cool objects is no fun because all the typing makes me miss Java:

use Local::Some::Real::Cool::Module; $this = Local::Some::Real::Cool::Module->new(); $that = Local::Some::Real::Cool::Module->new(); $more = Local::Some::Real::Cool::Module->new();

Sometime ago I learned I could set a string to the module name and use it instead:

use Local::Some::Real::Cool::Module; $gimme = 'Local::Some::Real::Cool::Module'; $this = $gimme->new(); $that = $gimme->new(); $more = $gimme->new();

That is better, but still kinda sucks. So I try to have the module return its own name and get it that way, but of course the return of use can't be used:

# Nope $gimme = use Local::Some::Real::Cool::Module;

Maybe the return of require can be used to grab the module name? Yes it can. But will I be sorry if I do? Any other suggestions?

#!/usr/bin/perl my $gimme = require Local::Some::Real::Cool::Module; import $gimme qw(some import stuff here); my $this = $gimme->new(); my $that = $gimme->new(); my $more = $gimme->new(); #----------------------------------------------------------- # Local/Some/Real/Cool/Module.pm #----------------------------------------------------------- package Local::Some::Real::Cool::Module; sub import { # . . . } sub new { return bless {}, shift; } 'Local::Some::Real::Cool::Module';

YuckUse

Replies are listed 'Best First'.
Re: use, require, and constructors
by fglock (Vicar) on Oct 26, 2004 at 22:40 UTC

    How about importing a constructor?

    use Local::Some::Real::Cool::Module qw( gimme );

    "gimme" would be something like this:

    package Local::Some::Real::Cool::Module; sub gimme { __PACKAGE__->new( @_ ) }
Re: use, require, and constructors (factories++)
by tye (Sage) on Oct 27, 2004 at 02:50 UTC

    Unfortunately, require will only return that value the first time you require the module, so you really shouldn't use this.

    It would be nice if require and/or use would return a factory (by default, just the class name). It probably wouldn't be hard to fix require (patch Perl) since it nearly works already. And in the chatterbox Larry said that Perl6's use will return a factory (at least that was how I understood it).

    In modern Perl, the closest I can come to this is initializing a factory variable. You'd use the OO module like:

    use Disney::Animation::Animal::Mouse::WithGloves( \my $Mickey ); # ... my $logo= $Mickey->new( "Smiling" );

    The OO module would have something like:

    sub import { my( $us, $ref )= @_; $$ref= $us if ref($ref); }

    Just as one example of how you could do it.

    - tye        

      It would be nice if require and/or use would return a factory (by default, just the class name).
      Problem with that is that other people are (ab)using require's return value for other things. Unless you just meant having require cache the true return value the first time and return it every time.

      If the module exports any subs, you can get the package name from them:

      $ cat Foo.pm package Foo; use strict; use warnings; use base "Exporter"; our @EXPORT = "bar"; sub bar { "baz" } 1; $ perl -we'use Foo; use B; print B::svref_2object(\&bar)->STASH->NAME' Foo
      (as long as the module didn't itself import the sub from elsewhere).

        If require were fixed to return the same value every time (caching the value from the first call), then I'd update all of my OO modules to end with __PACKAGE__; instead of 1; and document how to use that (if you are programming for a version of Perl where require has been fixed).

        Though my objects (like many Perl objects) very often have "user preference" type options that are best expressed once (in the use line) so I already provide a way for the module user to get a factory that can construct objects with the user's preferences already taken into account.

        An easy way to do this is to allow objects to be constructed from each other so my use lines typically let you list your preferences and where you'd like your master object to be stored. You can just use the one master object or you can use it as a factory (even though it is of the same class as the objects it will be creating).

        I'm amused that you appear to think I'd like to write

        B::svref_2object(\&function_exported_by_OO_module_of_which_there_shoul +d_not_be_any)->STASH->NAME->new( ... )

        in order to avoid typing the name of the module. :)

        - tye        

Re: use, require, and constructors
by PodMaster (Abbot) on Oct 26, 2004 at 23:21 UTC
    Type once then cut and paste. Really, avoding the names of things is not a good idea (too lazy). I don't even like the idea of an exported constructor. Just quit being lazy :)

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Re: use, require, and constructors
by Duco (Sexton) on Oct 27, 2004 at 22:14 UTC
    Another possibility is to alias the entire namespace into your own. In other words, you're effectively just making a short name for that package. Something like:

    *{__PACKAGE__.'::Module::'} = *{'Local::Some::Real::Cool::Module::'}; $object = Module->new();