tags:

views:

117

answers:

4

module foo/bar.pm

package foo::bar;
stuff
stuff
package foo::wizzy;
require Exporter;
our @ISA=qw(Exporter);
our @EXPORT=qw(x);
use constant
{
  x=>1
};

a consumer that goes use Foo::bar; does not get the foo::wizzy::x export

I know I can make it 2 separate modules, but still I should be able to make this work - shouldnt I

+7  A: 

When you call use foo::bar, what actually happens is essentially:

BEGIN {
    require foo::bar;
    foo::bar->import;
}

(see perldoc -f use)

So import is never getting called on foo::wizzy. If you want to import those symbols as well, you can call BEGIN { foo::wizzy->import } yourself (after use foo::bar). Or, as you said, just split these two packages into separate files, which would be much more human-readable.

(By the way, it's not advisable to use lower-cased package names, as those are generally reserved for perl pragmata.)

Ether
The OP could also write a custom `import` method for foo::bar that exports the stuff from Foo::wizzy. (Not that I'd do it that way.)
Michael Carman
@Michael: yeah, I only put packages together for back-of-a-napkin code, so by this point I'd go "f-- it, I'm not saving any time from having these two packages in one file" and split them.
Ether
+1 especially for the comment above.
Sinan Ünür
+8  A: 
hobbs
+1 I forgot about `export_to_level` and almost recreated the functionality ;-)
Sinan Ünür
Yeah, I always start to get a little defensive when I see someone else messing around with my symbol table.. it's like an invasion of personal space: you better be in an emergency, or married to me :)
Ether
+2  A: 

First off, I find it helpful to use enclosing braces to control scope when cramming multiple packages into one file. Also, enclosing the package in a BEGIN block makes it work more like a proper use was used to load it, but this is mostly if I am cramming the package into the main script.

use Foo is the same as BEGIN { require Foo; Foo->import }.

So, you have two choices:

  • call BEGIN{ Foo::Whizzy->import; } in your main script.
  • make Foo::Bar::import trigger Foo::Whizzy::import on the calling module.

In Foo/Bar.pm:

{ package Foo::Bar;
  use Exporter qw( export_to_level );

  # Special custom import.  Not needed if you call Foo::Whizzy->import
  sub import {
    shift;
    export_to_level('Foo::Whizzy', 1, @_ );
  }

  # stuff
  # stuff
}

{ package Foo::Whizzy;
  require Exporter;

  our @ISA=qw(Exporter);
  our @EXPORT=qw(x);
  use constant  { x=>1 };

}

1; # return true

In your main code:

use Foo::Bar;

# If you don't do a custom import for Foo::Bar, add this line:
BEGIN { Foo::Whizzy->import };
daotoad
+2  A: 

At the end of the module, put:

BEGIN { $INC{'foo/wizzy.pm'} = 1 }

Then code can just say:

use foo::bar;
use foo::wizzy;

to get foo::wizzy's exports.

ysth
ooo - thats a good one - thx
pm100