Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Tuesday August 07, 2007
03:34 AM

import Our::Code::*;

[ #34021 ]

A long time ago, Matt Trout mentioned that he's started using aliased a bit and wanted a feature like this:

use aliased 'Our::Code::*';

That would be conceptually equivalent to the following Java code:

import Our.Code.*;

Now imagine you have a directory structure like this:

lib/Our/Code/Customer.pm
lib/Our/Code/Datacenter.pm
lib/Our/Code/Item.pm
lib/ Our/Code/Office.pm
lib/Our/Code/Order.pm
lib/Our/Code/Server.pm
lib/Our/Code/ Server/Dedicated.pm

The above 'aliased' line would give you aliases like this:

use aliased 'Our::Code::*';

my $cust       = Customer->new;
my $datacenter = Datacenter->new;
my $item       = Item->new;
my $office     = Office->new;
my $order      = Order->new;
my $server     = Server->new;
my $ded_server = ServerDedicated->new;   # unsure of this

Traditionally, that would be something like this:

use Our::Code::Customer;
use Our::Code::Datacenter;
use Our::Code::Item;
use Our::Code::Office;
use Our::Code::Order;
use Our::Code::Server;
use Our::Code::Server::Dedicated;

my $cust       = Our::Code::Customer->new;
my $datacenter = Our::Code::Datacenter->new;
my $item       = Our::Code::Item->new;
my $office     = Our::Code::Office->new;
my $order      = Our::Code::Order->new;
my $server     = Our::Code::Server->new;
my $ded_server = Our::Code::Server::Dedicated->new;

Needless to say, you can see which one folks might like.

Of course, the devil's in the details and I think a module other than aliased would be called for with this experiment. There would also have to be customization options. For example, I think by default it shouldn't use those modules until the alias is actually invoked. Also, by default, we'd want to ensure that only one directory structure is searched and classes loaded from that directory. We might want descending into subdirectories to be optional. One also might want to be able to load and alias all classes in the format Our::Code::O*.

The biggest objection I expect to hear from folks is "mysterious action at a distance is bad!" I can understand that point and I would have raised it myself a long time ago, but I've been around the block long enough to realize why this works for Java so well: after you've been working on your business code long enough, you know what's in lib/Our/Code/*. Of course, it will have issues when you try to do this with lib/Our/Code/DateTime.pm in there. I think a CHECK block might help, not to mention invoking the alias should check if there's a competing entry in %INC. For example, with Our::Code::Order:

sub Order {
  my $class = 'Our::Customer::Order';
  if ( exists $INC{'lib/Order.pm'} ) {
    # die and noisily complain about a conflict
  }
  # load the class if not loaded
  return $class;
}

Unfortunately, class method calls sometimes dispatch to the namespace and sometimes would dispatch to the alias. It all depends on how the code is organized. This could be the biggest problem.

I have enough sympathy for the 'action at a distance' argument and a firm enough belief that this is different enough from aliased that the experiment definitely deserves to be in a different namespace. Suggestions? (Other than "please don't". If you don't like zucchini, don't eat it.)

It's also worth nothing that there's a broken import module on the CPAN and it hasn't been updated in 8 years.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • You might be able to use Module::Pluggable http://search.cpan.org/dist/Module-Pluggable/ [cpan.org]
  • The so called import-on-demand feature of Java:

    import foo.bar.*;

    is generally considered bad practice, good only at quick-and-dirty code. Tools like Eclipse help expand these evil statements into qualified imports after compiling and resolving the class names in the current source file.

    Some of the problems are mentioned at http://javadude.com/tools/importifier/ [javadude.com]

    • If you use a name that exists in more than one package, the Java compiler cannot determine which fully-qualified name to use. You need to spe
    • You know, I think you make a compelling argument. I'll have to consider this and I might just drop the idea.

      • It used to be pretty standard in Python to import the whole shebang as well (ie from foo import *) but that is frowned upon today as well. Mainly because of namespace pollution.

        You really should only call what you need and if you do somthing like Our::Code::*; You may be surprised by what you are importing (whether you did it intentionally or not).
  • For me, the beauty of 'aliased' lies mostly in its shortcutting of names. If I'd want to make an API to declare multiple of these in one, I would probably do...

    use aliased::all 'Foo::Bar' => qw( Baz Quux Fnord );

    my $baz   = Baz->new;
    my $quux  = Quux->new;
    my $fnord = Fnord->new;

    With this, it is IMO short enough, explicit enough, and contains no surprises.

    --
    Ordinary morality is for ordinary people. -- Aleister Crowley
  • ... after you've been working on your business code long enough, you know what's in lib/Our/Code/*.

    Java's an unreadable language because novices can't look at that program and instantly know where exactly every import came from. (Hey, this argument is fun to make!)