How do I keep subroutines Local to the libraries I am calling?

How do I keep subroutines Local to the libraries I am calling?

am 16.10.2006 17:05:51 von Alf McLaughlin

Hello all-
I am having a very simple problem and I cannot find the solution
anywhere. For this example, I'll invent a simple library:

BEGIN: {
package my_library;
use Exporter;
our @EXPORT(&mysub1);
}

sub my_sub1 {
return 'this is my_sub1';
}

sub my_sub2 {
return 'this is my sub2';
}

###END of library.

Now I have a simple script:

#!/usr/bin/perl

BEGIN: {
use my_library;
}

MAIN: {
my $foo = my_sub2();
print "$foo\n";
}

#end of script.

What is driving me crazy is that I would very much like it if my_sub2
stays local to my_library, but instead when I run this script I see the
message "this is my_sub2". What I would really like to do is keep
certain subroutines local to my libraries and until recently I thought
I was doing this by using @EXPORT. Could someone please set me
straight? I am trying to avoid the confusing situation where my script
also contains a subroutine called "my_sub2".

Thanks a lot,
Alf

Re: How do I keep subroutines Local to the libraries I am calling?

am 16.10.2006 18:26:19 von paduille.4059.mumia.w

On 10/16/2006 10:05 AM, Alf McLaughlin wrote:
> Hello all-
> I am having a very simple problem and I cannot find the solution
> anywhere. For this example, I'll invent a simple library:
>

Declare your package before your BEGIN block:
package my_library;

> BEGIN: {
> package my_library;

Don't declare the package in here.

> use Exporter;
> our @EXPORT(&mysub1);
> }
>
> sub my_sub1 {
> return 'this is my_sub1';
> }
>
> sub my_sub2 {
> return 'this is my sub2';
> }
>
> ###END of library.
>
> Now I have a simple script:
>
> #!/usr/bin/perl
>
> BEGIN: {
> use my_library;
> }
>
> MAIN: {
> my $foo = my_sub2();
> print "$foo\n";
> }
>
> #end of script.
>
> What is driving me crazy is that I would very much like it if my_sub2
> stays local to my_library, but instead when I run this script I see the
> message "this is my_sub2".

That's because you put my_sub2 in the main package. (Main is the default
package).

> What I would really like to do is keep
> certain subroutines local to my libraries and until recently I thought
> I was doing this by using @EXPORT. Could someone please set me
> straight? I am trying to avoid the confusing situation where my script
> also contains a subroutine called "my_sub2".
>
> Thanks a lot,
> Alf
>

Look at the examples in "perldoc perltoot"


--
Mumia W.
paduille.4059.mumia.w@earthlink.net
This is a temporary e-mail to help me catch some s-p*รก/m.

Re: How do I keep subroutines Local to the libraries I am calling?

am 16.10.2006 18:56:55 von Paul Lalli

Alf McLaughlin wrote:

> I am having a very simple problem and I cannot find the solution
> anywhere. For this example, I'll invent a simple library:
>
> BEGIN: {

This is not a BEGIN{} block. This is a block with the label BEGIN.
The statements within this block will not be executed at compile time.

Remove the colon.

> package my_library;

'package' is lexically scoped. By putting it inside the block, you
make it so that only the code in this block is in this package. Take
it out of the block. Really, get rid of the block entirely, it's not
doing a thing worth anything.

> use Exporter;
> our @EXPORT(&mysub1);

This is not valid syntax. you meant:
our @EXPORT = ('&mysub1');

> }
>
> sub my_sub1 {
> return 'this is my_sub1';
> }
>
> sub my_sub2 {
> return 'this is my sub2';
> }

Neither of these subroutines are in the package my_library, because
they're not in the same lexical scope as the package statement.

>
> ###END of library.
>
> Now I have a simple script:
>
> #!/usr/bin/perl
>
You forgot:
use strict;
use warnings;

> BEGIN: {
> use my_library;
> }

This is still not a BEGIN block. Get rid of the colon. And then get
rid of the block entirely. 'use' already happens at compile-time.

>
> MAIN: {

Why are you doing this? What point do you think this has?

> my $foo = my_sub2();
> print "$foo\n";
> }
>
> #end of script.
>
> What is driving me crazy is that I would very much like it if my_sub2
> stays local to my_library, but instead when I run this script I see the
> message "this is my_sub2".

Because my_sub2 was defined in package main, not package my_library.

> What I would really like to do is keep
> certain subroutines local to my libraries and until recently I thought
> I was doing this by using @EXPORT.

That's backwards. Using Exporter and the global @EXPORT variable
allows other packages direct access to a package's subroutines (without
fully qualifying), not prevents the access.

> Could someone please set me
> straight? I am trying to avoid the confusing situation where my script
> also contains a subroutine called "my_sub2".

All named subroutines are global. No way around that. But you can
have multiple subroutines with the same name by putting them in
different packages. Your central problem here is that for reasons
unknown, you decided to put your 'package' statement inside a block.
Stop doing that, and you'll be fine.

Paul Lalli

Re: How do I keep subroutines Local to the libraries I am calling?

am 16.10.2006 20:19:31 von Alf McLaughlin

> 'package' is lexically scoped. By putting it inside the block, you
> make it so that only the code in this block is in this package. Take
> it out of the block. Really, get rid of the block entirely, it's not
> doing a thing worth anything.

Thanks, Paul. I was definitely missing this point.


> >
> > MAIN: {
>
> Why are you doing this? What point do you think this has?

I like to organize my scripts using a block like this. Then, I can
localize variables to this block and call other sub routines from this
block and return values to pass to other subroutines; it helps me keep
track of what I'm doing. Is it bad? I am always looking for ways to
improve my Perl scripts so please let me know. I don't actually think
it's doing anything (I may as well call the block "FRAN" or "GREG").

Your comments have actually been an immense help. I was really doing a
lot of silly things, I can see, so I'll have to read up on Perl
libraries.

For now, here is my final version of things that I think is a better
way to do it:

The library:

package my_library;

sub my_sub1 {
return 'this is my_sub1';
}

sub my_sub2 {
return 'this is my_sub2';
}

1;
__END__

###END of library.

The script:

#!/usr/bin/perl

use my_library;

MAIN: {
my $foo = my_library::my_sub2();
print "$foo\n";
}

## END of script.


I believe this style of writing libraries will solve my basic problem
as opposed to what I was doing.

Re: How do I keep subroutines Local to the libraries I am calling?

am 16.10.2006 20:45:46 von Paul Lalli

Alf McLaughlin wrote:
> > Why are you doing this? What point do you think this has?
>
> I like to organize my scripts using a block like this. Then, I can
> localize variables to this block and call other sub routines from this
> block and return values to pass to other subroutines; it helps me keep
> track of what I'm doing. Is it bad? I am always looking for ways to
> improve my Perl scripts so please let me know. I don't actually think
> it's doing anything (I may as well call the block "FRAN" or "GREG").

That's actually exactly why it makes me do a double-take. By putting
it there, it's too easy for someone to be under the mistaken impression
that this block of code functions like the int main() function in C.
It doesn't. Limiting the scope of your variables is a good thing, and
I applaud you for making that decision. I'm just not sure labeling the
block MAIN: is the best of all choices.

> Your comments have actually been an immense help. I was really doing a
> lot of silly things, I can see, so I'll have to read up on Perl libraries.

FWIW, we generally call them "modules" in Perl, and you can read up on
them in:
perldoc perlmod

> For now, here is my final version of things that I think is a better
> way to do it:
>
> The library:
>
> package my_library;
>
> sub my_sub1 {
> return 'this is my_sub1';
> }
>
> sub my_sub2 {
> return 'this is my_sub2';
> }
>
> 1;
> __END__
>
> ###END of library.
>
> The script:
>
> #!/usr/bin/perl
>
> use my_library;
>
> MAIN: {
> my $foo = my_library::my_sub2();
> print "$foo\n";
> }
>
> ## END of script.
>
>
> I believe this style of writing libraries will solve my basic problem
> as opposed to what I was doing.

My only other suggestion is to make sure you add
use strict;
use warnings;
to *both* the module and the "main" file.

Paul Lalli