CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
using package in perl

 



naven8
Novice

Feb 3, 2012, 8:32 AM

Post #1 of 18 (3645 views)
using package in perl Can't Post

I am trying to use package in a normal perl program but i am not getting the expected results.


my $name = "ABCD";

package New;
$name = "XYZ";
print "$name \n";

package main;
print "$name \n";

-------------------------
expected results:
XYZ
ABCD

---------------
Actual o/p that i am getting
XYZ
XYZ


Why iam getting the unexpected results here. Do i need to use packages with only .pm files?


FishMonger
Veteran / Moderator

Feb 3, 2012, 8:56 AM

Post #2 of 18 (3643 views)
Re: [naven8] using package in perl [In reply to] Can't Post

The starting point would be to read the perldoc's related to modules.


Code
        perlmod             Perl modules: how they work 
perlmodlib Perl modules: how to write and use
perlmodstyle Perl modules: how to write modules with style
perlmodinstall Perl modules: how to install from CPAN
perlnewmod Perl modules: preparing a new module for distribution


http://perldoc.perl.org/index-language.html


naven8
Novice

Feb 3, 2012, 9:15 AM

Post #3 of 18 (3641 views)
Re: [FishMonger] using package in perl [In reply to] Can't Post

I am exploring the usage of package here.
The same thing is working when i remove "my"+"use strict". But i dont want to remove "use strict".
Is there any other solution.


FishMonger
Veteran / Moderator

Feb 3, 2012, 9:31 AM

Post #4 of 18 (3639 views)
Re: [naven8] using package in perl [In reply to] Can't Post

Please post a short, but complete script that demonstrates the problem.

Your original post was lacking too much of the details to give you any meaningful advise.


FishMonger
Veteran / Moderator

Feb 3, 2012, 9:40 AM

Post #5 of 18 (3638 views)
Re: [naven8] using package in perl [In reply to] Can't Post

Also, even though (one or more) packages can be defined within the .pl script, it's best to define the packages in their own .pm files and load them in the .pl file with a 'use' or 'require' statement.


naven8
Novice

Feb 3, 2012, 9:44 AM

Post #6 of 18 (3634 views)
Re: [FishMonger] using package in perl [In reply to] Can't Post

Getting Expected results with following:
#!/home/utils/perl-5.8.8/bin/perl -w
use warnings;

$name = "ABCD";
package New;
$name = "XYZ";
print "$name \n";
package main;
print "$name \n";
------------------------------------
Not working :
#!/home/utils/perl-5.8.8/bin/perl -w
use strict;
use warnings;

my $name = "ABCD";

package New;
$name = "XYZ";
print "$name \n";

package main;
print "$name \n";


FishMonger
Veteran / Moderator

Feb 3, 2012, 9:58 AM

Post #7 of 18 (3630 views)
Re: [naven8] using package in perl [In reply to] Can't Post

That's a scoping issue.

The package keyword creates a new namespace and as such, when using the strict pragma, $name declared in the 'main' namespace is not the same var as $name declared in the 'New' namespace.

Separate the packages into their own .pm files; it will reduce the confusion.


FishMonger
Veteran / Moderator

Feb 3, 2012, 10:03 AM

Post #8 of 18 (3629 views)
Re: [naven8] using package in perl [In reply to] Can't Post

Read this tutorial.

http://perl-begin.org/tutorials/perl-for-newbies/part3/#page--modules--DIR


budman
User

Feb 11, 2012, 12:26 PM

Post #9 of 18 (3578 views)
Re: [naven8] using package in perl [In reply to] Can't Post

For testing purposes, or sometimes inclusion of related modules, you need to separate the scopes because everything defaults to the main package.

Example:

Code
{ 
package MyPack::Funcs;
.... some code ...
our $myvar = 'package var';
1; # optional for inclusive packages, required for external
}

{
package MyPack;
import MyPack::Funcs;

print $MyPack::Funcs::myvar;

... code ...
1; # optional for inclusive packages
}

package main;

import MyPack;

... code ...


Normally, you would use the 'use' command to load the modules - this is for external packages (*.pm). The 'use' command is actually a function that performs a 'require' on the module name, and then an 'import' to load the file into the namespace/package.

The closure block { package ... } isolates each packages namespace, so they won't bleed into each other. Each package is now has a separate independent namespace.

If you run across 'use vars', this will probably be deco'd in new releases, so use the 'our' command on variables you want to share between modules.


You can try it without the imports, perl will try loading them implicitly as long as you don't call the modules with 'use'.

Look into Exporter if you want to limit what gets imported into the main namespace.

In your module 'MyPack' you can add:

Code
  use Exporter(); 
our @ISA = 'Exporter';
# explicit exports requires qw(sub1 sub2) in calling package
our @EXPORT = "sub1 sub2 sub3";
# global exports
our @EXPORT_OK = "sub4 sub5 $var";


Check out the perldoc perlmod for more tips.


(This post was edited by budman on Feb 11, 2012, 12:34 PM)


budman
User

Feb 11, 2012, 1:00 PM

Post #10 of 18 (3575 views)
Re: [naven8] using package in perl [In reply to] Can't Post

In your sample, you are updating the global name var


Code
#!/usr/bin/perl 

use strict;
use warnings;

# any vars declared as globals will be seen by packages

my $name = "ABCD"; # defined as global $main::name

{
use strict; # keep consistent for extern modules
use warnings;
package New;
# do not do this - you are depending on a extern variable
# that will lead to issues if module is extracted to external file and
# used by another script that does not declare the var before using the
# package.
# $name = "XYZ"; # updating global $main::name

# use a package var and then share with others if they need it
our $name = "XYZ"; # update package $name
print "Inside ". __PACKAGE__ ." name = $name \n";
}

package main;
printf "\$%s::name = %s\n", __PACKAGE__, $name;
print "\$New::name = $New::name\n";


Output:
Inside New name = XYZ
$main::name = ABCD
$New::name = XYZ


FishMonger
Veteran / Moderator

Feb 11, 2012, 1:55 PM

Post #11 of 18 (3572 views)
Re: [budman] using package in perl [In reply to] Can't Post


Quote

Code
my $name = "ABCD";  # defined as global $main::name


Incorrect. The 'my' keyword creates a lexical var, not a global. In your example it's a lexical var with file scope.


BillKSmith
Veteran

Feb 12, 2012, 8:22 AM

Post #12 of 18 (3537 views)
Re: [naven8] using package in perl [In reply to] Can't Post

You expect the behavior of package variables. (Your example works without 'strict' or 'my' because this becomes the default.) 'Strict' does not require you declare all your variables with 'my', it only requires you to declare all your variables. You can explicitly declare package variables under 'use strict'. In your case you need two package variables, both named '$name'. (One in each package).


Code
use strict; 
use vars qw ($name);
$name = "ABCD";

package New;
use vars qw ($name);
$name = "XYZ";
print "$name \n";

package main;
print "$name \n";

Good Luck,
Bill


budman
User

Feb 12, 2012, 8:59 AM

Post #13 of 18 (3535 views)
Re: [FishMonger] using package in perl [In reply to] Can't Post

Hi

Trying to understand why its called File scope.
Is 'my' making it static?

This is how I understand scoping

Code
my $name = "ABC";  # program or global scope 
{
my $name = "ABC"; # file scope (static) cannot be changed once set
sub static_name { $name }
}

sub {
my $name = "XYZ"; # function scope
for (@x) {
my $name = "123"; # block scope
}
}



Edit: I did some searching on scopes, I see now what you mean.
The my $name in the beginning has "til end of file" scope.
http://perl.plover.com/FAQs/Namespaces.html

Thanks
Rich


(This post was edited by budman on Feb 12, 2012, 9:20 AM)


FishMonger
Veteran / Moderator

Feb 12, 2012, 9:26 AM

Post #14 of 18 (3529 views)
Re: [budman] using package in perl [In reply to] Can't Post


Quote

Code
{  
my $name = "ABC"; # file scope (static) cannot be changed once set
sub static_name { $name }
}



Not correct. $name is block scoped and can be changed at any point within that block. That sub is a closure and returns the current value of $name.

Consider this:

Code
{ 
my $name = "ABC";
sub static_name { $name }

print static_name(), "\n";

$name = 'XYZ';
print static_name(), "\n";

$name = 'Bob';
}

print static_name(), "\n";



FishMonger
Veteran / Moderator

Feb 12, 2012, 9:34 AM

Post #15 of 18 (3526 views)
Re: [budman] using package in perl [In reply to] Can't Post

BTW, I would not use a block like that; instead I'd simply define the sub in the main:: package like this.


Code
sub static_name {  
my $name = "ABC";
return $name;
}

Or, even more simply

Code
sub static_name { "ABC" }



budman
User

Feb 12, 2012, 9:44 AM

Post #16 of 18 (3525 views)
Re: [FishMonger] using package in perl [In reply to] Can't Post


Quote
Not correct. $name is block scoped and can be changed at any point within that block. That sub is a closure and returns the current value of $name.


Correct. Any code in the closure can update name.
However, main cannot. Main can only update it with code provided by the closure block. If there is no code to change it, then the value becomes constant to main.


Code
{ 
my $name = "ABC";
sub static_name { $name }
print static_name(), "\n";
$name = 'XYZ';
print static_name(), "\n";
$name = 'Bob';
}

$name = "Ann";
print static_name(), " = $name \n";


Output:

ABC
XYZ
Bob = Ann


FishMonger
Veteran / Moderator

Feb 12, 2012, 10:02 AM

Post #17 of 18 (3523 views)
Re: [budman] using package in perl [In reply to] Can't Post

As written, that code won't compile under strict and if the goal is to simple create a static var, then the Readonly module would be the better approach.


Code
#!/usr/bin/perl 

use strict;
use warnings;
use Readonly;

Readonly::Scalar my $name => 'Bob';

print "$name\n";

$name = 'Ann';

Outputs:

Quote
D:\perl>test.pl
Bob
Modification of a read-only value attempted at D:\perl\test.pl line 11.



budman
User

Feb 12, 2012, 12:41 PM

Post #18 of 18 (3514 views)
Re: [FishMonger] using package in perl [In reply to] Can't Post

Correct. I was just using as an example for scoping purposes.
I would probably use Constant in that case.

Normally, I would only use a closure block to protect a counter. The new state command, from what I can see, eliminates the need for these closure blocks.

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives