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

V

Volker Nicolai

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
 
P

Paul Lalli

Volker said:
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_

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.
-------------------------------------------
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,
);

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.
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

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::.
Neither the 'announcement' of %p_hash with line _2_* nor the typeglob
line _3_* helps and I don't have any idea why.

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
 
F

Fabian Pilkowski

* Volker Nicolai said:
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;
use import_pack;
print "P_HASH: $p_hash{x} , $p_hash{y}\n";
-------------------------------------------

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;
-------------------------------------------

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__

If I run it without use stricts it is fine.
But if I use strict [...] I get:
Variable "%p_hash" is not imported at [...]
So where is the crux?

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
 
B

Brian McCauley

Fabian Pilkowski wrote:

[ In the context of an example .pm file ]
#!/usr/local/bin/perl -w

There's no shebang line in a module.
package import_pack;
use strict;

You forgot use warnings. Probably because you thought the shebang line
would do it.
 
F

Fabian Pilkowski

* Brian McCauley said:
Fabian Pilkowski wrote:

[ In the context of an example .pm file ]
#!/usr/local/bin/perl -w

There's no shebang line in a module.

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 ... ;-)
You forgot use warnings. Probably because you thought the shebang line
would do it.

Yes, that's what I thought. I mistaked perl modules for perl scripts in
this case.

thanks for correcting,
fabian
 
P

Peter Scott

#!/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

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).
 
V

Volker Nicolai

Paul Lalli said:
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

Thanks, Paul, especially that you made me see this stupid mistake.

But if this
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::.
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")
 
V

Volker Nicolai

Fabian Pilkowski said:
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__

If I run it without use stricts it is fine.
But if I use strict [...] I get:
Variable "%p_hash" is not imported at [...]
So where is the crux?

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

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";
 
F

Fabian Pilkowski

* Volker Nicolai said:
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?

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
 
F

Fabian Pilkowski

* Volker Nicolai said:
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...

In Paul's version all the vars are settled in package "main", regardless
in which file they are declared.
Please also see my answer to Paul (the name space change seem to not be
mandatory).

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
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,830
Latest member
ZADIva7383

Latest Threads

Top