import fails if package namespace != module path

Discussion in 'Perl Misc' started by neurocline@gmail.com, Sep 24, 2007.

  1. Guest

    I'm struggling with something. If I have a module, but the package
    namespace inside the module doesn't match the path passed to use, then
    import (with @EXPORT or @EXPORT_OK) doesn't work. There's something I
    don't understand, obviously, but I don't know where the fault is.

    If I do

    use Extra::Bits::Name qw(func);

    and my package is just in "package Name", then I get "Undefined
    subroutine &main::fucn" when I try to access just "func" ("Name::func"
    works fine). But if I rearranged paths so I can do "use Name
    qw(func)", then everything works.

    For example, I have a package contained in goober.pm that looks like
    this

    package goober;
    use strict;
    use warnings;

    require Exporter;
    our @ISA = qw(Exporter);
    our @EXPORT_OK = qw(gooberme);
    our $VERSION = '1.00';

    sub gooberme
    {
    print STDERR "yeppers\n";
    }

    and I have a main program that looks like this

    #!/usr/bin/perl
    use strict;
    use warnings;

    use FindBin;
    use lib "$FindBin::Bin/../../CorePerl";

    use Blizzard::goober qw(gooberme);
    gooberme();

    then I get "Undefined subroutine &main::gooberme called at ...".
    There's a reason why I can't just completely rearrange my library
    paths to make the includes come out matching the package names. Or
    rather - I can do that, it will be painful, and I didn't think it
    would be necessary.

    What am I missing? Obviously I don't understand something about use/
    require and how package namespaces work.
     
    , Sep 24, 2007
    #1
    1. Advertising

  2. Guest

    wrote:
    > I'm struggling with something. If I have a module, but the package
    > namespace inside the module doesn't match the path passed to use, then
    > import (with @EXPORT or @EXPORT_OK) doesn't work. There's something I
    > don't understand, obviously, but I don't know where the fault is.
    >
    > If I do
    >
    > use Extra::Bits::Name qw(func);
    >
    > and my package is just in "package Name", then I get "Undefined
    > subroutine &main::fucn" when I try to access just "func" ("Name::func"
    > works fine). But if I rearranged paths so I can do "use Name
    > qw(func)", then everything works.


    Your use statement tries to call:
    Extra::Bits::Name->import(qw(func))

    Since there is presumably no subroutine named Extra::Bits::Name::import and
    no array named @Extra::Bits::Name::ISA, then nothing happens. "use"
    doesn't look into the used file to see what package it should call import
    on, it bases that decision on the filename/module name indicated in the
    "use" statement itself.

    In this case, I don't see a work around that would be easier or work better
    than just rearranging your code to conform to Perl's expectations regarding
    module names and package names.

    In another context, I'm contemplating of violating that expectation myself,
    so that I can change "configuration" simply by changing a use, without
    changing anything else.

    #use Foo_config1;
    use Foo_config2;

    my $dir = $Foo::data_dir;
    my $dbh = Foo::get_database_handle();

    I'm thinking that if I do go this route, I should avoid using import at
    all, or at least avoid optional imports, to avoid the problem you see.


    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    The costs of publication of this article were defrayed in part by the
    payment of page charges. This article must therefore be hereby marked
    advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
    this fact.
     
    , Sep 24, 2007
    #2
    1. Advertising

  3. Ben Morrow Guest

    Quoth :
    > I'm struggling with something. If I have a module, but the package
    > namespace inside the module doesn't match the path passed to use, then
    > import (with @EXPORT or @EXPORT_OK) doesn't work.


    Don't do that then. :)

    > There's something I don't understand, obviously, but I don't know
    > where the fault is.


    use Module ARGS;

    is exactly equivalent to

    BEGIN {
    require Module;
    Module->import(ARGS);
    }

    except that the ->import step is omitted if Module doesn't have an
    import method. If you really really want to do this, you can have a
    module called Foo/Bar.pm which defines a package Baz by using

    BEGIN {
    require Foo::Bar;
    Baz->import(ARGS);
    }

    instead of use Foo::Bar... however, I can't help thinking you're going
    about this the wrong way. What are you trying to achieve? If you just
    want to put the module somewhere else, you can ask perl to search that
    somewhere else with

    use lib 'somewhere/else';

    > If I do
    >
    > use Extra::Bits::Name qw(func);
    >
    > and my package is just in "package Name", then I get "Undefined
    > subroutine &main::fucn" when I try to access just "func" ("Name::func"
    > works fine). But if I rearranged paths so I can do "use Name
    > qw(func)", then everything works.


    Yes. This is how the Perl module system works. The argument to use is
    supposed to be a module name, not a strange way of writing a path; how
    that name is resolved to a path is governed by @INC (manipulated with
    lib.pm).

    > For example, I have a package contained in goober.pm that looks like
    > this
    >
    > package goober;


    Don't use lowercase package names. They are reserved for pragmas:
    modules that affect how perl parses your program. In general it's best
    to name your packages after something reasonably unique, so you don't
    get conflicts later; I have a convention of using BMORROW::Blarg::* for
    modules used by the Blarg project, where BMORROW is my CPAN id.

    > and I have a main program that looks like this
    >
    > #!/usr/bin/perl
    > use strict;
    > use warnings;
    >
    > use FindBin;
    > use lib "$FindBin::Bin/../../CorePerl";


    Since you already know about lib.pm, what stopped you trying

    use lib "$FindBin::Bin/../../CorePerl/Blizzard";

    ? You can keep both 'use lib' lines, if you have some modules in the
    CorePerl directory and some in CorePerl/Blizzard (though that seems like
    a bad idea). In general it would be better to use File::Spec to create
    that path; however, that may not be important in your case.

    Ben
     
    Ben Morrow, Sep 24, 2007
    #3
  4. Ben Morrow Guest

    Quoth :
    >
    > In this case, I don't see a work around that would be easier or work better
    > than just rearranging your code to conform to Perl's expectations regarding
    > module names and package names.
    >
    > In another context, I'm contemplating of violating that expectation myself,
    > so that I can change "configuration" simply by changing a use, without
    > changing anything else.
    >
    > #use Foo_config1;
    > use Foo_config2;
    >
    > my $dir = $Foo::data_dir;
    > my $dbh = Foo::get_database_handle();
    >
    > I'm thinking that if I do go this route, I should avoid using import at
    > all, or at least avoid optional imports, to avoid the problem you see.


    Would it not be better to do something like

    package Foo;

    use warnings;
    use strict;
    use Carp;

    sub import {
    shift eq '-config' or croak 'must supply a config!';
    my $config = 'Foo::' . shift;

    # the 1 works around a bug in some versions of 5.8 :(
    eval "require $config; 1" or croak $@;

    $config->export_to_level(1, @_);
    }

    1;

    package main;

    use Foo -config => 'config1', qw/$data_dir get_database_handle/;

    my $dir = $data_dir;
    my $dbh = get_database_handle();

    __END__

    This assumes Foo::* inherits Exporter::import, of course, though that
    can be worked around if necessary (it's harder than you might think,
    because you have to get caller() right).

    Or you could do the thing properly and use OO :). Note that you don't
    *have* to have Foo::config1 inherit from Foo: you can have the reverse,
    and you can decide what to inherit from at runtime. File::Spec does
    this, for example.

    package Foo;

    use warnings;
    use strict;

    use Carp;

    our @ISA;

    sub import {
    my $config = "Foo::$_[0]";
    eval "require $config; 1" or croak $@;
    @ISA = $config;
    }

    1;

    package main;

    use Foo config1;

    my $dir = Foo->data_dir;
    my $dbh = Foo->get_database_handle();

    __END__

    Ben
     
    Ben Morrow, Sep 25, 2007
    #4
  5. Guest

    > Your use statement tries to call:
    > Extra::Bits::Name->import(qw(func))


    and

    > use Module ARGS;
    >
    > is exactly equivalent to
    >
    > BEGIN {
    > require Module;
    > Module->import(ARGS);
    > }


    Thanks. I knew that at one level, but I wasn't thinking it through.
    Xho called it out clearly enough that it penetrated my skull. I wonder
    if I can make extra import routines above and beyond the one Exporter
    makes.

    One reason I was playing with use vs package names is that I'm trying
    to make self-installing modules (through a code reference pushed into
    @INC that's just a few lines of HTTP fetch), and so I want my modules
    to have a unique namespace so I can distinguish them from internal
    ones. And I don't want to through all the code and edit their uses of
    names.

    Thanks for the help, I'm going to try a few things out.
     
    , Sep 25, 2007
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. George P
    Replies:
    3
    Views:
    709
    Alex Martelli
    Sep 11, 2004
  2. plb
    Replies:
    0
    Views:
    418
  3. plb
    Replies:
    0
    Views:
    336
  4. Xiao Jianfeng
    Replies:
    2
    Views:
    782
    Ben Finney
    Dec 16, 2005
  5. Dr. Rüdiger Kupper

    Nested module import clutters package namespace?

    Dr. Rüdiger Kupper, Feb 28, 2008, in forum: Python
    Replies:
    1
    Views:
    403
    Matthew Woodcraft
    Feb 29, 2008
Loading...

Share This Page