Re: Writing Modules/namespace polution
by dragonchild (Archbishop) on Mar 16, 2005 at 15:53 UTC
|
You're confusing exporting with object-oriented programming. You don't need Exporter to have an object, which is what you have. Change your script to:
#!/usr/bin/perl
use strict;
use warnings;
use mymodule;
my $m = mymodule->new();
print "My Test\n";
$m->Func1();
$m->Func2("Fluffy", 5);
Func1();
Func2("Fluffy", 5);
sub Func1 { print "Func1() in main!\n" }
sub Func2 { print "I'm still in main! (@_)\n" }
See what happens?
Being right, does not endow the right to be rude; politeness costs nothing. Being unknowing, is not the same as being stupid. Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence. Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
| [reply] [d/l] |
|
The little light goes on =)....
Thanks...I'm trying to do a OO method, but I didn't realize the object had all the methods by default, which makes sense as they are essentially protected by virtue of the fact that you have to use the object.
| [reply] |
|
package Example::Module;
use strict;
sub new { bless {}, shift }
sub foo {
my ($s, $v1, $v2) = @_;
print "Hi '$v1' and '$v2'\n";
}
1;
Script
use strict;
use Example::Module;
# add a new sub to the package
sub Example::Module::bar {
my ($s, $v1, $v2) = @_;
print "Bye '$v1' and '$v2'\n";
}
my $em = Example::Module->new;
$em->bar("one", "two");
# call the sub not as a method
Example::Module::foo('one', 'two', 'three');
# change the existing sub
*Example::Module::foo = sub {
my ($s, $v1, $v2) = @_;
print "Oops '$v1' and '$v2'\n";
};
$em->foo("one", "two");
| [reply] [d/l] [select] |
|
|
Re: Writing Modules/namespace polution
by ikegami (Patriarch) on Mar 16, 2005 at 15:58 UTC
|
use strict;
use warnings;
use mymodule;
print "My Test\n";
Func1(); # ERROR!
Func2("Fluffy", 5); # ERROR!
But check this out:
use strict;
use warnings;
use mymodule qw( Func1 ); # Import Func1
#use mymodule qw( Func2 ); # This won't work since
# Func2 is not in @EXPORT_OK.
print "My Test\n";
Func1();
Func2("Fluffy", 5); # ERROR!
You should never export methods. As you can see, there's no reason to do so. All functions in a package are tied to the object blessed to that package, whether you use Exporter or not.
and how can I prevent it as it seems to be allowing everything into the calling script's namespace?
It's possible to disguise a function using lexicals and/or closures so that noone outside the package can call it, but there's no need to do so. Write proper documentation instead.
| [reply] [d/l] [select] |
|
Thanks ikegami,
I can see how the exporter is supposed to work now. I read so much on making modules and looking at what other people had done, I just ended up combining both ideas which was wrong.
Regards Paul.
| [reply] |
Re: Writing Modules/namespace polution
by tlm (Prior) on Mar 17, 2005 at 01:39 UTC
|
use strict;
sub Foo::bar {
print 'called on line ', (caller)[2], ": $_[0]\n" and $_[0];
}
my $frobozz = bless \&Foo::bar, 'Foo';
$frobozz->bar('eenie');
$frobozz->bar('eenie')->('meenie');
$frobozz->('eenie');
Foo->bar('eenie');
Foo->bar('eenie')->bar('meenie');
Foo::bar('eenie');
'Foo'->bar('eenie');
'Foo::bar'->('eenie');
"Foo'bar"->('eenie'); # Perl trivia
# bar('eenie'); # bombs!
require Exporter;
@Foo::ISA = ('Exporter');
@Foo::EXPORT_OK = ('bar');
Foo->import('bar');
bar('eenie');
__END__
Make sure you understand why each output line is generated (except the one corresponding to the code line marked as "Perl trivia"--that one's optional), and why un-commenting out the line that begins with # bar causes a run-time error. If, after you work through it, something still doesn't make sense, ask.
Note! The above is certainly not an example of good coding. Its only purpose is to illustrate some aspects of Perl.
| [reply] [d/l] [select] |
Re: Writing Modules/namespace polution
by chas (Priest) on Mar 16, 2005 at 16:03 UTC
|
Actually, the default exports should be in @EXPORT, not @EXPORT_OK. The only thing I notice immediately is that I believe you should "use Exporter" not "require Exporter" in the module file (Update: plus the other posted comments...)
chas | [reply] |
|
Notwithstanding the fact that he doesn't appear to need to export anything -- as pointed out by other posts -- I'm not so sure it's advisable to suggest using @EXPORT very often. I realize a lot of well known and good modules do this, but most of the time, I think it makes more sense to use @EXPORT_OK and let the caller specify what they want to import.
| [reply] [d/l] [select] |
|
Agreed, but aside from the object/non-object mixup which I didn't catch, I interpreted the original poster's comments as indicating that he expected use mymodule; would make the entries in @EXPORT_OK available without explicit package referencing. My misunderstanding, I guess...
chas
| [reply] [d/l] |
|
| [reply] [d/l] |
|
I believe you should "use Exporter" not "require Exporter"
I believe you should "require Exporter" or "use base 'Exporter'" not "use Exporter".
The exporter module defines &Exporter::import so that it can be inheritied by other modules. Calling Exporter::import('Exporter') doesn't really make sense.
| [reply] |
|
Doing a "use Exporter;" will not do anything different than a "require Exporter;" because the import() function in Exporter doesn't do anything because Exporter doesn't define @EXPORT or @EXPORT_OK.
The only difference between "use base Exporter;" and either "use Exporter;" or "require Exporter;" is that "use base" will modify @ISA for you and the others make you modify it yourself. You either have to have Exporter in your @ISA or have done something like *import = \&Exporter::import; to get the benefits of Exporter.
Nothing more, nothing less.
Being right, does not endow the right to be rude; politeness costs nothing. Being unknowing, is not the same as being stupid. Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence. Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
| [reply] [d/l] |
|
Well, I just checked in the Camel books. The 3rd edition does indicate "require Exporter;" in modules, but the 2nd edition (which I learned from) has "use Exporter;" in modules in most of the examples (although there was a "require Exporter;" in an example.) Randal Schwartz's book "Learning Perl Objects, References & Modules" says "...As a module author, all you do is add:
use Exporter;
our @ISA = qw(Exporter);
I just made a module skeleton using h2xs, and "require Exporter;" appears in the module file. So maybe either will suffice..I'll go with the "require" form since that's what h2xs produced.
chas
(Update: Hadn't seen Dragonchild's reply yet - that seems to settle the difference. Fixed typo.) | [reply] [d/l] |