Namespace And Separate Modules

Discussion in 'Perl Misc' started by Hal Vaughan, Sep 17, 2005.

  1. Hal Vaughan

    Hal Vaughan Guest

    I'm having a problem understanding namespace with modules. If I have a
    program and it uses some modules (say mod1, mod2, and mod3), I thought that
    the names I export from those modules are available in the main program's
    namespace -- and ONLY in that program's namespace.

    I also was under the understanding that any variables global to, say, mod2,
    when set from the main program, would ONLY be set in that "instance" of
    mod2. So if, for example, mod1 also used mod2 (with a separate "use mod2;"
    statement within mod1), any global variables set in the main program's
    instance of mod2 should be in a completely different namespace from the one
    within mod1, where mod1 uses mod2. In other words, while both the main
    program and mod1 use mod2, the program's mod2 should maintain variables
    separately from mod1's mod2.

    However when I run tests, that is not the case (code and sample run included
    below). When I test it, if I make changes in the main program's mod2, they
    show up in mod1's mod2, and vice versa. For me, this is actually a
    benefit, but it is not how I understood namespace to work.

    Is this the behavior I should expect? Is it documented or intended, so I
    can count on it always happening? If I use a module (say mod1) in the main
    program, will, and use a number of other modules from the main program, if
    any of those other modules use mod1, will the variables in each instance of
    mod1 stay consistant with each other?

    Thanks for any comments. This is rather difficult for me to follow and make
    sure I understand it correctly.

    Hal
    ----------------------------------------------------------------------
    Program code:

    #!/usr/bin/perl
    use fakemods::mod1;
    use fakemods::mod2;
    use fakemods::mod3;
    print "This is the main program\n";
    setval1(1); printval1();
    setval12(2); printval2();
    setvalx12(3); printval2(); printvalx12();
    setval2(4); printval2(); printvalx12();
    ----------------
    fakemods/Mod1.pm listing:

    package fakemods::mod1;
    use Exporter;
    use fakemods::mod2;
    use strict;
    our ($mainval);

    BEGIN {
    use vars qw(@ISA);
    @ISA = qw(Exporter);
    our @EXPORT = qw(setval1 printval1 setval11 setval12 setval13
    setvalx12 printvalx12);
    }
    sub setval1 {
    $mainval = $_[0];
    return;
    }
    sub printval1 {
    print "Value 1: $mainval\n";
    return;
    }
    sub setval11 {
    my $val = shift(@_);
    main::fakemods::mod1::setval1($val);
    return;
    }
    sub setval12 {
    my $val = shift(@_);
    main::fakemods::mod2::setval2($val);
    return;
    }
    sub setval13 {
    my $val = shift(@_);
    main::fakemods::mod3::setval3($val);
    return;
    }
    sub setvalx12 {
    my $val = shift(@_);
    setval2($val);
    return;
    }
    sub printvalx12 {
    printval2();
    return;
    }
    1;

    ----------------
    fakemods/Mod2.pm listing:

    package fakemods::mod2;
    use Exporter;
    use strict;
    our ($mainval);
    BEGIN {
    use vars qw(@ISA);
    @ISA = qw(Exporter);
    our @EXPORT = qw(setval2 printval2 setval21 setval22 setval23);
    }
    sub setval2 {
    $mainval = $_[0];
    return;
    }
    sub printval2 {
    print "Value 2: $mainval\n";
    return;
    }
    sub setval21 {
    my $val = shift(@_);
    main::fakemods::mod1::setval1($val);
    return;
    }
    sub setval22 {
    my $val = shift(@_);
    main::fakemods::mod2::setval2($val);
    return;
    }
    sub setval23 {
    my $val = shift(@_);
    main::fakemods::mod3::setval3($val);
    return;
    }
    1;
    ----------------
    fakemods/Mod3.pm listing:

    package fakemods::mod3;
    use Exporter;
    use strict;
    our ($mainval);
    BEGIN {
    use vars qw(@ISA);
    @ISA = qw(Exporter);
    our @EXPORT = qw(setval3 printval3 setval31 setval32 setval33);
    }
    sub setval3 {
    $mainval = $_[0];
    return;
    }
    sub printval3 {
    print "Value 3: $mainval\n";
    return;
    }
    sub setval31 {
    my $val = shift(@_);
    main::fakemods::mod1::setval1($val);
    return;
    }
    sub setval32 {
    my $val = shift(@_);
    main::fakemods::mod2::setval2($val);
    return;
    }
    sub setval33 {
    my $val = shift(@_);
    main::fakemods::mod3::setval3($val);
    return;
    }
    1;

    Test output:
    ----------------
    [hal@workstation:~]$ modtest
    This is the main program
    Value 1: 1
    Value 2: 2
    Value 2: 3
    Value 2: 3
    Value 2: 4
    Value 2: 4
     
    Hal Vaughan, Sep 17, 2005
    #1
    1. Advertising

  2. Hal Vaughan

    Guest

    Hal Vaughan wrote:
    > I'm having a problem understanding namespace with modules. If I have a
    > program and it uses some modules (say mod1, mod2, and mod3), I thought that
    > the names I export from those modules are available in the main program's
    > namespace -- and ONLY in that program's namespace.


    No, exporting symbols creates aliases. A symbol exported from mod1 to
    main makes an entry in the main:: symbol table that points to exactly
    the same place as the one in the mod1::.

    > I also was under the understanding that any variables global to, say, mod2,
    > when set from the main program, would ONLY be set in that "instance" of
    > mod2.


    No, you are way off track. In the normal course of events there is no
    concept of "instance" unless you create obejcts.

    > So if, for example, mod1 also used mod2 (with a separate "use mod2;"
    > statement within mod1), any global variables set in the main program's
    > instance of mod2 should be in a completely different namespace from the one
    > within mod1, where mod1 uses mod2.


    No, you are way off track. That said Perl is sufficiently flexible
    that you _could_ create a mod2 with those semantics by providing your
    own custom import() method.

    > Is this the behavior I should expect?


    Yes

    > Is it documented or intended,


    Yes

    > so I can count on it always happening?


    Unless the author of mod2 decides otherwise.

    > If I use a module (say mod1) in the main
    > program, will, and use a number of other modules from the main program, if
    > any of those other modules use mod1, will the variables in each instance of
    > mod1 stay consistant with each other?


    Unless the author of mod1 decides otherwise.
     
    , Sep 17, 2005
    #2
    1. Advertising

  3. Hal Vaughan <> writes:

    > I'm having a problem understanding namespace with modules. If I have a
    > program and it uses some modules (say mod1, mod2, and mod3), I thought that
    > the names I export from those modules are available in the main program's
    > namespace -- and ONLY in that program's namespace.
    >
    > I also was under the understanding that any variables global to, say, mod2,
    > when set from the main program, would ONLY be set in that "instance" of
    > mod2.


    There is only one "instance" of a given name space. Importing symbols from a
    name space into another doesn't make copies of the original's data, it uses
    typeglobs to create aliases that refer to the same variable.

    > However when I run tests, that is not the case (code and sample run included
    > below). When I test it, if I make changes in the main program's mod2, they
    > show up in mod1's mod2


    There is only *one* mod2.

    Have a look at "perldoc perlmod", especially the section titled "Symbol Tables"
    for details about how symbols are imported by Exporter.pm. In a nutshell, when
    you do this:

    *main::foo = \$mod2::foo;

    $main::foo and $mod2::foo are now two different names for the *same* variable.

    sherm--

    --
    Cocoa programming in Perl: http://camelbones.sourceforge.net
    Hire me! My resume: http://www.dot-app.org
     
    Sherm Pendley, Sep 17, 2005
    #3
  4. Hal Vaughan <> wrote:

    > Program code:
    >
    > #!/usr/bin/perl


    use warnings;
    use strict;


    > fakemods/Mod1.pm listing:

    ^^^
    ^^^
    > package fakemods::mod1;

    ^^^
    ^^^

    Case matters.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Sep 17, 2005
    #4
  5. Hal Vaughan

    Hal Vaughan Guest

    wrote:

    > Hal Vaughan wrote:
    >> I'm having a problem understanding namespace with modules. If I have a
    >> program and it uses some modules (say mod1, mod2, and mod3), I thought
    >> that the names I export from those modules are available in the main
    >> program's namespace -- and ONLY in that program's namespace.

    >
    > No, exporting symbols creates aliases. A symbol exported from mod1 to
    > main makes an entry in the main:: symbol table that points to exactly
    > the same place as the one in the mod1::.
    >
    >> I also was under the understanding that any variables global to, say,
    >> mod2, when set from the main program, would ONLY be set in that
    >> "instance" of mod2.

    >
    > No, you are way off track. In the normal course of events there is no
    > concept of "instance" unless you create obejcts.
    >
    >> So if, for example, mod1 also used mod2 (with a separate "use mod2;"
    >> statement within mod1), any global variables set in the main program's
    >> instance of mod2 should be in a completely different namespace from the
    >> one within mod1, where mod1 uses mod2.

    >
    > No, you are way off track. That said Perl is sufficiently flexible
    > that you _could_ create a mod2 with those semantics by providing your
    > own custom import() method.
    >
    >> Is this the behavior I should expect?

    >
    > Yes
    >
    >> Is it documented or intended,

    >
    > Yes
    >
    >> so I can count on it always happening?

    >
    > Unless the author of mod2 decides otherwise.
    >
    >> If I use a module (say mod1) in the main
    >> program, will, and use a number of other modules from the main program,
    >> if any of those other modules use mod1, will the variables in each
    >> instance of mod1 stay consistant with each other?

    >
    > Unless the author of mod1 decides otherwise.


    I think I've got it, but let me try another example (this is so different
    from what I expected I want to be sure I've got it). Say I have a program
    that uses MyMods::Log and MyMods::process. Inside MyMods::process I also
    use MyMods::Log. There is a function in MyMods::Log that goes like this:

    sub dolog {
    my $msg = $_[0];
    #$logfile is a global variable, set by the original program on startup
    open(LOG, ">$logfile");
    print LOG "$msg\n";
    close LOG;
    return;
    }

    Now, if I understand you correctly, when the program sets $logfile, which is
    a global variable in MyMods::Log (but it isn't exported), when I call
    dolog() from inside MyMods::process, $logfile will have the same value as
    when it is called from the original program. So any module the program
    uses can call dolog() and it will write to the same file as long as I have
    "use MyMods::Log" in that module. I don't have to specify or do anything
    to make sure they all log to the same file -- that is a feature of Perl.

    Is that correct?

    Hal
     
    Hal Vaughan, Sep 17, 2005
    #5
  6. Hal Vaughan

    Joe Smith Guest

    Hal Vaughan wrote:

    > I think I've got it, but let me try another example (this is so different
    > from what I expected I want to be sure I've got it). Say I have a program
    > that uses MyMods::Log and MyMods::process. Inside MyMods::process I also
    > use MyMods::Log.


    You have to understand two things.
    1) Perl uses %INC to keep track of which modules have been loaded
    so each on is only loaded once. To see a typical %INC, try this:
    bash% perl -MFile::Find -le 'print "$_ = $INC{$_}" for sort keys %INC'

    2) The 'use' statement tells Perl to load the module if it has not
    already been loaded, then call the module's import() function. The
    import() function causes aliases to be made in the current namespace
    for variables defined in the used module.

    In file MyProg.pl:
    package main;
    use MyMods::Log;
    $logfile = "test.log";

    In file MyMods/Process.pm:
    package MyMods::process;
    print $logfile;

    In this case, $main::logfile, $MyMods::Log::logfile, and
    $MyMods::process::logfile are entries in three different
    symbol tables that point to the exact same variable.

    As for code references, the variables accessable to the
    function are the ones visible when the code was parsed.
    It makes no difference whether you call it as
    main::dolog(), MyMods::Log::dolog(), or MyMods::process::dolog();
    the dolog() function will have at its disposal the same
    variables in each case.
    -Joe
     
    Joe Smith, Sep 18, 2005
    #6
    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. EvgueniB
    Replies:
    1
    Views:
    655
    Anthony Borla
    Dec 15, 2003
  2. Frank Fredstone
    Replies:
    1
    Views:
    460
    Jean-Francois Briere
    Jun 27, 2006
  3. Peng Yu
    Replies:
    4
    Views:
    344
    Steven D'Aprano
    Oct 20, 2009
  4. Victor Hooi
    Replies:
    7
    Views:
    120
    Peter Otten
    Oct 30, 2013
  5. Kalinni Gorzkis
    Replies:
    3
    Views:
    102
Loading...

Share This Page