How to import symbols and semantics from one namespace into another

Ask a Question related to PERL Beginners, Design and Development.

  1. #1

    Default How to import symbols and semantics from one namespace into another

    Hi, this question has to do with importing names from one package into another. In my case, both packages reside in the same file, and I simply want to import all the package-global symbols from the one package into the other. Can anyone say how to do this? Here's a bunch of tries that didn't work.

    test_import.pl
    --------------
    package main;

    print "Hi world\n";
    $x = dosomething();
    print "did something and got $x\n";
    exit;

    package SomePackage;
    sub dosomething{
    return time;
    }

    Obviously this isn't going to work because symbol dosomething is not defined in package main. (In this trivial example I could just say $x = SomePackage::dosomething(), but I have dozens of functions and I would prefer to simply import them into the namespace of main. Also, apart from this specific instance, I want to understand what I can do in general.)

    The documentation for perlmod implies there's an import method that's part of exporter, so I tried something like this.

    test_import.pl
    --------------
    package main;
    SomePackage::import(qw(dosomething));
    print "Hi world\n";
    $x = dosomething();
    print "did something and got $x\n";
    exit;

    package SomePackage;
    use Exporter;
    @ISA = qw(Exporter);
    @EXPORT = qw(dosomething);
    sub dosomething{
    return time;
    }

    outcome:
    --------
    Undefined subroutine &SomePackage::import called at test_import.pl line 2.

    Another variation:

    test_import.pl
    --------------
    package main;
    import SomePackage (qw(dosomething));
    print "Hi world\n";
    $x = dosomething();
    print "did something and got $x\n";
    exit;

    package SomePackage;
    use Exporter;
    @ISA = qw(Exporter);
    @EXPORT = qw(dosomething);
    sub dosomething{
    return time;
    }

    outcome:
    --------
    (Not what I expected; why didn't it tell me main::import is undefined?)
    Hi world
    Undefined subroutine &main::dosomething called at test_import.pl line 5.

    Another variation:

    test_import.pl
    --------------
    package main;
    use SomePackage;
    print "Hi world\n";
    $x = dosomething();
    print "did something and got $x\n";
    exit;

    package SomePackage;
    use Exporter;
    @ISA = qw(Exporter);
    @EXPORT = qw(dosomething);
    sub dosomething{
    return time;
    }

    outcome:
    --------
    This obviously won't work because 'use' expects a module name, not a package name. Same issue with 'require'.

    Can't locate SomePackage.pm in @INC (@INC contains: d:/app/xampp/perl/lib D:/app/xampp/perl/lib D:/app/xampp/perl/site/lib .) at test_import.pl line 3.
    BEGIN failed--compilation aborted at test_import.pl line 3.

    That's it. Any ideas?


    __________________________________________________ ________________
    New! Unlimited Netscape Internet Service.
    Only $9.95 a month -- Sign up today at [url]http://isp.netscape.com/register[/url]
    Act now to get a personalized email address!

    Netscape. Just the Net You Need.
    mcdavis941@netscape.net Guest

  2. Similar Questions and Discussions

    1. IPTables namespace - how to commandeer namespace
      I have a Perl module, IPTables::IPv4, that I've been developing for some time, and that is in the CPAN repository. I've expanded the module to...
    2. flock() semantics?
      Hi all, I'm writing an app which uses a flat file to store a *short* list of simple key/value pairs. However having read the flock() man page,...
    3. Formal Language Semantics
      Does anyone know where I can get the formal language semantics for Ruby (assuming such a thing exists)? Thank you, Christopher Aycock Oxford...
    4. module_function semantics
      Hi all! I'm trying to understand some code in the stdlib (drb/drb.rb, to be particular). Is there any difference between: module Foo ...
  3. #2

    Default Re: How to import symbols and semantics from one namespace into another


    > Hi, this question has to do with importing names from one package into
    another. In my case, both packages reside in the same file, and I
    simply want to import all the package-global symbols from the one
    package into the other. Can anyone say how to do this? Here's a bunch
    of tries that didn't work.
    >
    This doesn't make a lot of sense to me, if you are going to export them
    all why bother? The big reason for the separate packages is to avoid
    namespace pollution, which if you export everything you have just
    counteracted. At least put them in a separate file, and use it? But to
    each their own....
    > test_import.pl
    > --------------
    > package main;
    >
    > print "Hi world\n";
    > $x = dosomething();
    > print "did something and got $x\n";
    > exit;
    >
    > package SomePackage;
    > sub dosomething{
    > return time;
    > }
    >
    > Obviously this isn't going to work because symbol dosomething is not
    defined in package main. (In this trivial example I could just say $x =
    SomePackage::dosomething(), but I have dozens of functions and I would
    prefer to simply import them into the namespace of main. Also, apart
    from this specific instance, I want to understand what I can do in general.)
    >
    > The documentation for perlmod implies there's an import method that's
    part of exporter, so I tried something like this.
    >
    > test_import.pl
    > --------------
    > package main;
    > SomePackage::import(qw(dosomething));
    > print "Hi world\n";
    > $x = dosomething();
    > print "did something and got $x\n";
    > exit;
    >
    > package SomePackage;
    > use Exporter;
    > @ISA = qw(Exporter);
    > @EXPORT = qw(dosomething);
    > sub dosomething{
    > return time;
    > }
    >
    Close, but import is a method not a plain function, so you need to call
    it on the class,

    SomePackage->import();
    > outcome:
    > --------
    > Undefined subroutine &SomePackage::import called at test_import.pl line 2.
    >
    > Another variation:
    >
    > test_import.pl
    > --------------
    > package main;
    > import SomePackage (qw(dosomething));
    > print "Hi world\n";
    > $x = dosomething();
    > print "did something and got $x\n";
    > exit;
    >
    > package SomePackage;
    > use Exporter;
    > @ISA = qw(Exporter);
    > @EXPORT = qw(dosomething);
    > sub dosomething{
    > return time;
    > }
    >
    > outcome:
    > --------
    > (Not what I expected; why didn't it tell me main::import is undefined?)
    > Hi world
    > Undefined subroutine &main::dosomething called at test_import.pl line 5.
    >
    Because the syntax you causes Perl to realize it is supposed to be a
    method, now the problem is that SomePackage hasn't done any exporting
    yet, because it hasn't been seen yet.
    > Another variation:
    >
    > test_import.pl
    > --------------
    > package main;
    > use SomePackage;
    > print "Hi world\n";
    > $x = dosomething();
    > print "did something and got $x\n";
    > exit;
    >
    > package SomePackage;
    > use Exporter;
    > @ISA = qw(Exporter);
    > @EXPORT = qw(dosomething);
    > sub dosomething{
    > return time;
    > }
    >
    > outcome:
    > --------
    > This obviously won't work because 'use' expects a module name, not a
    package name. Same issue with 'require'.
    >
    > Can't locate SomePackage.pm in @INC (@INC contains:
    d:/app/xampp/perl/lib D:/app/xampp/perl/lib D:/app/xampp/perl/site/lib
    ..) at test_import.pl line 3.
    > BEGIN failed--compilation aborted at test_import.pl line 3.
    >
    Which sort of tells you that you ought to be moving in that direction,
    but that's up to you...
    > That's it. Any ideas?
    >
    Go with your method call syntax above (or the one provided below) and
    either move the definition of SomePackage to the top of the script, or
    wrap the definition in a BEGIN {} compile time block.... so,

    #!/usr/local/bin/perl
    use strict; # Always!
    use warnings; # usually!

    Some::Package->import();

    print "Hi world\n";
    my $x = dosomething();
    print "did something and got $x\n";
    exit;

    BEGIN {
    package Some::Package;
    require Exporter;
    our @ISA = qw(Exporter);
    our @EXPORT = qw(dosomething);
    sub dosomething {
    return time;
    }
    }

    HTH,

    [url]http://danconia.org[/url]
    Wiggins D Anconia Guest

  4. #3

    Default Re: How to import symbols and semantics from one namespace into another

    On Wed, Jan 28, 2004 at 01:32:14PM -0500, [email]mcdavis941@netscape.net[/email] wrote:
    > Hi, this question has to do with importing names from one package into
    > another. In my case, both packages reside in the same file, and I
    > simply want to import all the package-global symbols from the one
    > package into the other. Can anyone say how to do this? Here's a
    > bunch of tries that didn't work.
    Thanks for showing what you've tried. First couple snipped.
    > Another variation:
    >
    > test_import.pl
    > --------------
    > package main;
    > import SomePackage (qw(dosomething));
    > print "Hi world\n";
    > $x = dosomething();
    > print "did something and got $x\n";
    > exit;
    >
    > package SomePackage;
    > use Exporter;
    > @ISA = qw(Exporter);
    > @EXPORT = qw(dosomething);
    > sub dosomething{
    > return time;
    > }
    >
    > outcome:
    > --------
    > (Not what I expected; why didn't it tell me main::import is undefined?)
    > Hi world
    > Undefined subroutine &main::dosomething called at test_import.pl line 5.
    This one will work if you swap the order of the two packages in the
    file. Last example snipped.
    > That's it. Any ideas?
    This might be simpler:

    package main;
    *dosomething = \&SomePackage::dosomething;
    print "Hi world\n";
    $x = dosomething();
    print "did something and got $x\n";
    exit;

    package SomePackage;
    sub dosomething{
    return time;
    }

    --
    Paul Johnson - [email]paul@pjcj.net[/email]
    [url]http://www.pjcj.net[/url]
    Paul Johnson Guest

  5. #4

    Default Re: How to import symbols and semantics from one namespace into another


    On Jan 28, 2004, at 10:32 AM, [email]mcdavis941@netscape.net[/email] wrote:
    > Hi, this question has to do with importing names from one package into
    > another.
    [..]
    > outcome:
    > --------
    > This obviously won't work because 'use' expects a module name, not a
    > package name. Same issue with 'require'.
    >
    > Can't locate SomePackage.pm in @INC (@INC contains:
    > d:/app/xampp/perl/lib D:/app/xampp/perl/lib D:/app/xampp/perl/site/lib
    > .) at test_import.pl line 3.
    > BEGIN failed--compilation aborted at test_import.pl line 3.
    >
    > That's it. Any ideas?
    [..]

    first off my complements on the most excellent work so far.

    Well there are a couple of basic solutions here.

    a. decide the perl modules should be in an external file
    so that one can simply use the

    use SomePackage;

    approach that simply requires that the module be external.

    b. decide that the 'package' approach needs to be in the
    perl script itself and adopt the oo-ish type of approach
    so that one winds up accessing the methods by indirection
    through say a blessed reference, rather than by importation
    into the package main.

    for more details you might want to

    a. pick up the perl modules and reference book.
    <http://www.oreilly.com/catalog/lrnperlorm/>

    b. see my stock rant
    <http://www.wetware.com/drieux/CS/lang/Perl/PM/quick_pm.html>

    Since basically I go with the idea that perl modules really
    belong as perl modules and then one has a simpler overall
    management problem. First because then multiple scripts
    can use the package, then as you so elegantly have demonstrated,
    because it winds up becomeing so much simpler than trying to
    work around managing the namespace issues on one's own.



    ciao
    drieux

    ---

    Drieux Guest

  6. #5

    Default Re: How to import symbols and semantics from one namespace into another

    On Wed, Jan 28, 2004 at 01:32:14PM -0500 [email]mcdavis941@netscape.net[/email] wrote:
    > Hi, this question has to do with importing names from one package into
    > another. In my case, both packages reside in the same file, and I
    > simply want to import all the package-global symbols from the one
    > package into the other. Can anyone say how to do this? Here's a
    > bunch of tries that didn't work.
    >
    > test_import.pl
    > --------------
    > package main;
    >
    > print "Hi world\n";
    > $x = dosomething();
    > print "did something and got $x\n";
    > exit;
    >
    > package SomePackage;
    > sub dosomething{
    > return time;
    > }
    >
    > Obviously this isn't going to work because symbol dosomething is not
    > defined in package main. (In this trivial example I could just say $x
    > = SomePackage::dosomething(), but I have dozens of functions and I
    > would prefer to simply import them into the namespace of main. Also,
    > apart from this specific instance, I want to understand what I can do
    > in general.)
    >
    > The documentation for perlmod implies there's an import method that's
    > part of exporter, so I tried something like this.
    >
    > test_import.pl
    > --------------
    > package main;
    > SomePackage::import(qw(dosomething));
    import() is a method and not a function. When you call it as a function
    it no longer obeyes inheritance and thus cannot be found since
    SomePackage inherits import() from Exporter.
    > print "Hi world\n";
    > $x = dosomething();
    > print "did something and got $x\n";
    > exit;
    >
    > package SomePackage;
    > use Exporter;
    > @ISA = qw(Exporter);
    > @EXPORT = qw(dosomething);
    > sub dosomething{
    > return time;
    > }
    >
    > outcome:
    > --------
    > Undefined subroutine &SomePackage::import called at test_import.pl line 2.
    >
    > Another variation:
    >
    > test_import.pl
    > --------------
    > package main;
    > import SomePackage (qw(dosomething));
    > print "Hi world\n";
    > $x = dosomething();
    > print "did something and got $x\n";
    > exit;
    >
    > package SomePackage;
    > use Exporter;
    > @ISA = qw(Exporter);
    > @EXPORT = qw(dosomething);
    > sub dosomething{
    > return time;
    > }
    >
    > outcome:
    > --------
    > (Not what I expected; why didn't it tell me main::import is undefined?)
    Because here you called it as a method. This is indirect method
    invocation:

    import SomePackage qw(bla);

    is the same as

    SomePackage->import(qw(bla));

    Here perl was indeed able to call import(). However, the reason why it
    still doesn't work as you expect is the order of execution. If you do

    package SomePackage;
    require Exporter;
    @ISA = qw(Exporter);
    @EXPORT = qw(dosomething);
    sub dosomething{
    return time;
    }

    package main;
    SomePackage->import( qw/dosomething/ );
    print dosomething();

    things will work. This has to do with the fact that @EXPORT is still
    empty when you do the import() and when you have package main before the
    exporting package. That is because assignment happens at runtime.

    In case you wonder why you got no error with

    package main;
    SomePackage->import(...);
    package SomePackage;
    use Exporter;
    @ISA = qw(Exporter);

    even though @ISA was still empty by the time you called
    SomePackage->import, this is because 'import' and 'unimport' are two
    special cases. They can always be called as method even when they do not
    exist nor are inherited. So in fact you can also do:

    package main;
    main->import( qw/bla/ );
    __END__

    and wont get any error.

    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus}) !JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexi ixesixeseg;y~\n~~dddd;eval

    Tassilo Von Parseval Guest

  7. #6

    Default Re: How to import symbols and semantics from one namespace into another

    On Jan 28, [email]mcdavis941@netscape.net[/email] said:
    >Hi, this question has to do with importing names from one package into
    >another. In my case, both packages reside in the same file, and I simply
    >want to import all the package-global symbols from the one package into
    >the other. Can anyone say how to do this? Here's a bunch of tries that
    >didn't work.
    The fact that they're in the same file is why your test cases all fail.
    >$x = dosomething();
    >exit;
    >
    >package SomePackage;
    >sub dosomething{
    >return time;
    >}
    >
    >Obviously this isn't going to work because symbol dosomething is not
    >defined in package main. (In this trivial example I could just say $x =
    >SomePackage::dosomething(), but I have dozens of functions and I would
    >prefer to simply import them into the namespace of main. Also, apart
    >from this specific instance, I want to understand what I can do in
    >general.)
    Right.
    >The documentation for perlmod implies there's an import method that's
    >part of exporter, so I tried something like this.
    Right. The 'import' method is a part of Exporter.pm, NOT of SomePackage.
    Thus, calling SomePackage::import() isn't going to work, since SomePackage
    doesn't HAVE an 'import' function.

    SomePackage->import('dosomething');

    would have worked. It's the same as

    import SomePackage 'dosomething';

    They're method-calling syntaces, not function calls.
    >import SomePackage (qw(dosomething));
    >$x = dosomething();
    >exit;
    >
    >package SomePackage;
    >use Exporter;
    >@ISA = qw(Exporter);
    >@EXPORT = qw(dosomething);
    >sub dosomething{
    >return time;
    >}
    >(Not what I expected; why didn't it tell me main::import is undefined?)
    >Undefined subroutine &main::dosomething called at test_import.pl line 5.
    This is because you run into a problem caused by the the package being in
    the same file as your program. Some things in Perl are done at
    compile-time, and others are done at run-time. Functions are parsed at
    compile-time, which is why this code doesn't die because it can't find the
    'foo' function:

    foo();

    sub foo { print 100 }

    If subroutine definitions weren't parsed ahead of time, Perl wouldn't know
    you'd made a 'foo' function.

    In your code, simplified as follows, the problem is thus: Perl doesn't
    know to use Exporter's 'import' method, and so it uses SomePackage's
    'import' method. However, as the documentation states, if a package
    doesn't HAVE an 'import' method, it silently fails (that is, no warning
    message is given, and no error is thrown).

    SomePackage->import('foo');
    foo();

    package SomePackage;
    require Exporter;
    @ISA = 'Exporter';
    @EXPORT = 'foo';
    sub foo { print "foo!\n" }

    You see, @ISA and @EXPORT aren't defined until Perl reaches them when
    EXECUTING your program. And since the first thing Perl executes is the
    'import' call, those arrays are defined too late to help.

    One way to fix this is with a BEGIN block:

    SomePackage->import('foo');
    foo();

    BEGIN {
    package SomePackage;
    require Exporter;
    @ISA = 'Exporter';
    @EXPORT = 'foo';
    sub foo { print "foo!\n" }
    }

    The stuff in the BEGIN block is executed at compile-time. Therefore, when
    Perl executes SomePackage->import('foo'), it will know to look at
    Exporter's 'import' method, and things will work properly.

    --
    Jeff "japhy" Pinyan [email]japhy@pobox.com[/email] [url]http://www.pobox.com/~japhy/[/url]
    RPI Acacia brother #734 [url]http://www.perlmonks.org/[/url] [url]http://www.cpan.org/[/url]
    <stu> what does y/// stand for? <tenderpuss> why, yansliterate of course.
    [ I'm looking for programming work. If you like my work, let me know. ]

    Jeff 'Japhy' Pinyan Guest

  8. #7

    Default Re: How to import symbols and semantics from one namespace into another

    "Wiggins d Anconia" <wiggins@danconia.org> wrote:
    >
    >
    >> Hi, this question has to do with importing names from one package into
    >another. In my case, both packages reside in the same file, and I
    >simply want to import all the package-global symbols from the one
    >package into the other. Can anyone say how to do this? Here's a bunch
    >of tries that didn't work.
    >>
    >
    >This doesn't make a lot of sense to me, if you are going to export them
    >all why bother? The big reason for the separate packages is to avoid
    >namespace pollution, which if you export everything you have just
    >counteracted. At least put them in a separate file, and use it? But to
    >each their own....
    >
    <snip old posts>

    Wiggins d Anconia,

    Thanks for your usual helpful answers, which do so much to make this list such a treasure trove for beginners.

    To answer your valid questions about "why would you want to do that":

    my circumstance is that I have a 10,000 line standalone command-line Perl program which I am refactoring into working as both a web app (Apache+Mod_perl+MySQL) and a command-line app. I'm not yet clear on what either the file or object architecture will be, which is why I'm not carving pieces out into separate files quite yet. All of the code written so far is pretty tightly coupled, again making it nontrivial to partition. It also has some long CPU-bound computation sequences, and I'm reluctant to make changes which would add overhead.

    Long story short, I'm casting about for solutions and trying to find out what all my options are. Even if not applicable to this particular case, it seems reasonable that some day you're going to want to import all symbols and semantics from one namespace into another (which doesn't have to be main:: ... it could be some other package). And it's kind of an interesting question just from an academic perspective. TMTOWTDI with Perl.

    I also find that it's really convenient, for now, to have all my source in one file (at least until I'm sure of the new architecture), for the same reason that someone on the list has advocated merging all the perl docs into a single file: for supereasy search and, in my case, replace. Also, as I transition into a packaged system of namespaces, I have a lot of code that expects a lot of names to be omnipresent (about 250 total subs, maybe half as object methods and half plain old subroutines); again it might be convenient to be able to put names in packages but still have them omnipresent until I'm clear how it all fits together.

    But you're right, in the end I'll probably end up with packages in their own files, included with 'use' just like most normal people would do. :)

    Thanks again!




    __________________________________________________ ________________
    New! Unlimited Netscape Internet Service.
    Only $9.95 a month -- Sign up today at [url]http://isp.netscape.com/register[/url]
    Act now to get a personalized email address!

    Netscape. Just the Net You Need.
    mcdavis941@netscape.net Guest

  9. #8

    Default Re: How to import symbols and semantics from one namespace into another


    On Jan 28, 2004, at 11:24 PM, [email]mcdavis941@netscape.net[/email] wrote:
    [..]
    > my circumstance is that I have a 10,000 line standalone command-line
    > Perl program which I am refactoring into working as both a web app
    > (Apache+Mod_perl+MySQL) and a command-line app. I'm not yet clear on
    > what either the file or object architecture will be, which is why I'm
    > not carving pieces out into separate files quite yet. All of the
    > code written so far is pretty tightly coupled, again making it
    > nontrivial to partition. It also has some long CPU-bound computation
    > sequences, and I'm reluctant to make changes which would add overhead.
    ouch. Given this context it makes some reasonable sense
    why you were trying to solve it all in one file. But you
    may need to rethink your strategy a bit here, and work
    on the slow and steady decoupling of the code so that
    you wind up with two different code lines and their
    supporting common collection of perl modules.

    foo_cli - the classical command line code
    foo_web - the web based app

    both of which use the Foo::Monkey suite of modules.

    This way you can work out what will really be required to
    be added to the web app itself...

    [..]
    > I also find that it's really convenient, for now, to have all my
    > source in one file (at least until I'm sure of the new architecture),
    > for the same reason that someone on the list has advocated merging all
    > the perl docs into a single file: for supereasy search and, in my
    > case, replace. Also, as I transition into a packaged system of
    > namespaces, I have a lot of code that expects a lot of names to be
    > omnipresent (about 250 total subs, maybe half as object methods and
    > half plain old subroutines); again it might be convenient to be able
    > to put names in packages but still have them omnipresent until I'm
    > clear how it all fits together.
    [..]

    with 250 subs you will want to sort out which of them
    have clean API's and as such can be easily pulled out as is.
    By clean, I mean they are not expecting anything to have
    water falled into them, nor are they doing the side effect
    of setting things "globally" that were not passed into them.

    I can appreciate the idea that it is easier to hunt them down
    in one file in one editor - but you might want to also look
    at the advantage of having more than one file open in more
    than one editor...

    But as japhy has already noted, if you want to put it all into
    one file you can use the BEGIN block and then start sorting
    out your package spaces:

    SomePackage->import('foo');
    foo();
    FOO::Bar->foo("bed time again");

    BEGIN {
    package SomePackage;
    require Exporter;
    our @ISA = 'Exporter';
    our @EXPORT = 'foo';
    sub foo { print "foo!\n" }

    package FOO::Bar;
    sub foo { my ($me,$arg) = @_; print "have arg: $arg\n"; }
    }



    ciao
    drieux

    ---

    Drieux Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139