"Variable ... is not imported..." using an imported variable from a module

Discussion in 'Perl Misc' started by Volker Nicolai, Jul 1, 2005.

  1. Hi,

    I have read a lot about use strict and the visibility of variables
    but still can not understand why my following problem occurs:
    I have this small script:
    -------------------------------------------
    #!/usr/local/bin/perl

    #use strict; # _1_
    use import_pack;
    # use vars qw($p_hash); # _2_
    # *p_hash = \%main::p_hash; # _3_

    # print "P_HASH: $::p_hash{x} , $::p_hash{y}\n"; # _4_
    print "P_HASH: $p_hash{x} , $p_hash{y}\n"; # _5_

    -------------------------------------------
    and the module import_pack.pm:
    -------------------------------------------
    #!/usr/local/bin/perl

    use Exporter;

    @ISA = qw(Exporter);
    @EXPORT = qw(%p_hash);

    %p_hash = (
    x => 123,
    y => 888,
    );

    1;
    -------------------------------------------

    If I run it without use stricts it is fine.
    But if I use strict (_1_) then I need line _4_* instead of _5_,
    otherwise I get:
    Variable "%p_hash" is not imported at import_test.pl line 9
    Neither the 'announcement' of %p_hash with line _2_* nor the typeglob
    line _3_* helps and I don't have any idea why. I thought the typeglob must be
    pretty much the same as using the full var name (with package) in the
    print statement.
    So where is the crux?
    (* uncommented :)

    Thanks for helping!
    Volker
     
    Volker Nicolai, Jul 1, 2005
    #1
    1. Advertisements

  2. Volker Nicolai

    Paul Lalli Guest

    strict is in place here. All package variables must be fully
    qualified. Thus, you get a syntax error trying to use %main::p_hash
    without fully qualifiying it.
    strict is not in place here. Thus, you are allowed to use
    %main::p_hash without fully qualifying it.
    Correct. Without strictures, the main script is allowed to use
    %main::p_hash without fully qualifying.
    Correct. %p_hash is not imported. Because your .pm file is in package
    main::, whereas the 'use import_pack;' statement attempts to import
    from package import_pack::.
    The "announcement" fails because you attempted to "announce" $p_hash
    rather than %p_hash. Two wholly unrelated variables. If you change
    that to:
    use vars qw(%p_hash);
    or, preferably:
    our %p_hash;
    The code will execute as expected.

    Hope this makes sense.
    Paul Lalli
     
    Paul Lalli, Jul 1, 2005
    #2
    1. Advertisements

  3. Well, you know you should use strict. But please do it in your modules
    too. After doing so, you have to declare your vars used in your module.
    But remember to declare each var you want to export with our() instead
    of my() -- better yet: each var you want to access from outside. Btw, I
    don't see a declaration of your package in that package. I'd write it as
    something like:


    #!/usr/local/bin/perl -w

    package import_pack;
    use strict;
    use Exporter;

    our @ISA = qw(Exporter);
    our @EXPORT = qw(%p_hash);

    our %p_hash = (
    x => 123,
    y => 888,
    );

    1;
    __END__

    I suggest to fix your module first. To understand the error message you
    have to know what use() is doing (see `perldoc -f use`). In short, it
    require()s the file and tries to call import() from the package. The
    latter is your problem. It's not possible to call import_pack->import()
    since there is no package called "import_pack". It is just part of the
    file's name and that is not what Perl uses as the default package name.
    The default package is called "main", and all you have done in the file
    "import_pack.pm" is done in package "main" though.

    Your script is running fine with stricts if you only add the declaration
    of the package's name in your package file. But familiarize yourself
    with using strict in your modules too. My example above shows you what
    you need for that. Btw, our() creates exactly the same type of globals
    as you would do without any declaration under "no strict", but it has
    the same scoping rules as a declaration with my(). Please read `perldoc
    -f our` for details.

    regards,
    fabian
     
    Fabian Pilkowski, Jul 1, 2005
    #3
  4. Fabian Pilkowski wrote:

    [ In the context of an example .pm file ]
    There's no shebang line in a module.
    You forgot use warnings. Probably because you thought the shebang line
    would do it.
     
    Brian McCauley, Jul 1, 2005
    #4
  5. You're right. But it is not disallowed to put a comment in the first
    line of a module file. It was just a silly thing to let this comment
    looking like a shebang line ... ;-)
    Yes, that's what I thought. I mistaked perl modules for perl scripts in
    this case.

    thanks for correcting,
    fabian
     
    Fabian Pilkowski, Jul 1, 2005
    #5
  6. Volker Nicolai

    Peter Scott Guest

    This is one of the most confusing messages this side of "... will not stay
    shared..."

    It is worth noting that you could get the same message with just this
    script and no modules:

    #!/path/to/perl
    use strict;
    %main::p_hash = ();
    print $p_hash{x};

    When perl gets to the last line, it sees a variable with no package
    qualifier. Since strict vars is in effect, it looks to see if it's
    a lexical, or permitted by use vars, or if it's $a/$b, etc - no dice on
    any of those - or if it's imported into the current package.

    You did no import, though. Because "use import_pack" is a compile time
    "require import_pack" followed by "import_pack->import", and you had no
    package called "import_pack", there was no call to Exporter->import.

    At this point, perl is going to complain about the unqualified variable,
    but it tries to be helpful and looks to see if there's a package variable
    with the same name that isn't imported (this isn't quite what the flow of
    control is intended to do but the effect is the same). Since you set
    %p_hash in main:: (in a separate scope where strict wasn't enabled, thus
    letting you get away with it), perl finds that and helpfully suggests that
    you're referring to the wrong imported variable.

    If all this is too confusing, just remember to set strict in all files and
    for the target of a use statement to begin with a package declaration of
    the same name (especially if it's using the Exporter).
     
    Peter Scott, Jul 2, 2005
    #6
  7. Thanks, Paul, especially that you made me see this stupid mistake.

    But if this
    is true, why does it work after the correction ($p_hash -> %p_hash) ??
    The package name is still 'wrong' then. It looks to me that it is not
    mandatory that a module's file and package name are identical or how
    could I interpret that?
    (Despite this is written in "Programming Perl")
     
    Volker Nicolai, Jul 4, 2005
    #7
  8. Thanks to you too, Fabian, but why does it work after I have corrected the
    error, Paul Lalli has found - this works with the old module, without
    any name space change by package...
    ---------------------------------------
    #!/usr/local/bin/perl

    use strict;
    use import_pack;
    use vars qw(%p_hash);

    print "P_HASH: $p_hash{x} , $p_hash{y}\n";
     
    Volker Nicolai, Jul 4, 2005
    #8
  9. When doing it this way, there is no other package than "main" involved.
    Sure, you has a second file (import_pack.pm) but all the code therein is
    written as part of package "main". All the exporting stuff is senseless
    then, because it will set @main::ISA, @main::EXPORT and %main::p_hash
    directly. Try out to miss out the lines

    use Exporter;
    @ISA = qw(Exporter);
    @EXPORT = qw(%p_hash);

    in your "import_pack.pm". That is, what you really do in this case. This
    is what Paul has written: "%p_hash is not imported. Because your .pm
    file is in package main::, [...]".

    When using another package (that is only if you have the "package" line
    in your code) you're creating the desired vars @import_pack::ISA,
    @import_pack::EXPORT and %import_pack::p_hash. And because of using
    "Exporter" this %import_pack::p_hash is exported into package "main". I
    thought you want using Exporter.pm since you've written "use Exporter".

    Fimally, *you* have to decide what *you* really want.

    regards,
    fabian
     
    Fabian Pilkowski, Jul 4, 2005
    #9
  10. In Paul's version all the vars are settled in package "main", regardless
    in which file they are declared.
    It is mandatory if you really want to export something. That is what I
    thought when reading your "use Exporter".

    Please also see my answer there.

    regards,
    fabian
     
    Fabian Pilkowski, Jul 4, 2005
    #10
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.