package-variable-declaration question - perl

What are the differences ( if any ) for me as the user of the package "Test::Test" between this two package-versions:
Test::Test;
require Exporter;
#ISA = qw(Exporter);
#EXPORT = qw(hello);
use strict; use warnings;
our $c = 3;
sub hello {
print "$_\n" for 0 .. $c;
}
.
Test::Test;
require Exporter;
#ISA = qw(Exporter);
#EXPORT = qw(hello);
$c = 3;
sub hello {
print "$_\n" for 0 .. $c;
}

It's a good practice to always enable strict and warnings. These pragmas help you to catch many simple errors and typos.
These two samples are equivalent. But the first one is preferred, because it explicitly declares the global variable $c using our and enables strictures and warnings.

FWIW, the proper way to write this module is like this:
package Test::Test;
use strict;
use warnings;
use Exporter 'import'; # gives you the import method directly
our #EXPORT = qw(hello);
my $c = 3;
sub hello {
print "$_\n" for 0 .. $c;
}
See perldoc Exporter for the best practices on writing modules with exports, for various scenarios.
I would also suggest changing the name of this package, as the Test:: namespace is already in use by core modules and CPAN distributions.

Variables in perl are by default global, regardless of whether they are declared in a module or not. The "my", "local" and "our" keywords scope the variable in different ways. In your example, "our $c" restricts the visibility of the variable to your package (unless you chose to export it, but that's another story).
So, for your latter example, any other piece of code that access and modify $c will impact your code too.
See http://perldoc.perl.org/functions/our.html for the official documentation on the "our" keyword.

Related

Importing variable into Perl package

I'm writing a basic program whose core logic is split across several project-specific modules for cleanliness (keeping subroutines organised by their purpose in the program's logic).
Suddenly had trouble exposing an option from the main package in one of the modules, and using the our statement appeared to have no effect.
For brevity, I'll copy+paste an isolated test case I wrote to examine this behaviour:
main.pl
#!/usr/bin/perl
use warnings;
use strict;
use File::Basename;
# The variable to be read by the module.
our $verbose = 1;
# Load Output.pm from directory
use lib dirname "$0";
use Output;
write_message "Hello, world\n";
Output.pm
package Output;
use warnings;
use strict;
use parent "Exporter";
our #EXPORT = qw(write_message);
# Should be imported?
our $verbose;
sub write_message {
print $_[0] unless !$verbose;
}
1;
Expected result: "Hello, world"
Actual result: Dead silence
It's quite possible that what I'm trying to achieve isn't even possible in Perl, as this isn't the intended use of modules (and heck, I understand why that'd be the case).
I'm still quite new to Perl and there are some things I'm struggling to wrap my head around. I've seen people recommend using the our declarator to expose a variable across packages, but I can't understand why this isn't working.
PS: If anybody knows a better approach to splitting an app's program-specific logic between modules, I'd appreciate some pointers too. :) But first and foremost, I'd prefer to learn why our-ing a variable isn't working.
An our statement just creates a package variable (whereas my creates a lexical variable). It has nothing to do with exporting
The best option is probably to declare the variable in the Output package and access it as $Output::verbose elsewhere. Like this
main.pl
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename;
use lib dirname $0;
use Output;
$Output::verbose = 1;
write_message "Hello, world\n";
Output.pm
package Output;
use strict;
use warnings;
use Exporter 5.57 'import';
our #EXPORT = qw/ write_message /;
our $verbose;
sub write_message {
print $_[0] if $verbose;
}
1;
Note that I have also removed the incorrect quotes from around $0, and ever since version 5.57 of Exporter it has been possible (and preferable) to import it's import subroutine instead of subclassing it
our declares a package variable in the current package. The one in main.pl refers to $main::verbose; the one in Output.pm refers to $Output::verbose.
You can use the full name $main::verbose to access the variable from anywhere, but you can't really "export" it because exporting refers to making symbols accessible to users of your module. You're trying to do the opposite.

Perl module class method vs ordinary subroutine

So I was wondering if there is any difference in usage between a Perl class method and an ordinary subroutine from a standard module. Is there a time you would use one over the other? For this example, I'm assuming that no object methods are present in either module.
Quick little main class here:
#!/usr/local/bin/perl
use strict;
use warnings;
use Foo;
use Bar;
my $arg1 = "blah";
my ($str1, $str2);
$str1 = Foo::subroutine($arg1);
$str2 = Bar->subroutine($arg1);
exit(0);
Package Foo would hold my ordinary subroutine call
use strict;
use warnings;
package Foo;
sub subroutine {
my $arg = shift;
my $string = "Ordinary subroutine arg is $arg\n";
return $string;
}
1;
Package Bar would hold my class method call
use strict;
use warnings;
package Bar;
sub subroutine {
my $class = shift;
my $arg = shift;
my $string = "Class method arg is $arg\n";
return $string;
}
1;
Normally if I'm writing Perl code, I would just use the class method option (like with the Bar example), but I started pondering this question after reading some code from a former coworker that used the syntax like in the Foo example. Both seem to do the same thing inherently, but there seems to be more than meets the eye.
The decider is whether your Module is an object-oriented module or not.
If Module is simply a container for a collection of subroutines, then I would expect it to use Exporter and offer the opportunity to import a subset of its subroutines into the calling name space. An example is List::Util
On the other hand, if there is a constructor Module::new, and the intention is to use it in an OO manner, then you shouldn't mix simple subroutines in with methods (except perhaps for private subroutines that the module uses internally). An example is LWP::UserAgent
So I would expect the sources to be written like one or the other of these, and not a mixture in between. Of course there are always circumstances where a rule of thumb should be ignored, but nothing comes to mind in this case.
Foo.pm
use strict;
use warnings;
package Foo;
use Exporter 'import';
our #EXPORT_OK = qw/ subroutine /;
sub subroutine {
my ($arg) = #_;
"Ordinary subroutine arg is $arg\n";
}
1;
Bar.pm
use strict;
use warnings;
package Bar;
sub new {
my $class = shift;
bless {}, $class;
}
sub subroutine {
my $class = shift;
my ($arg) = #_;
"Class method arg is $arg\n";
}
1;
main.pl
#!/usr/local/bin/perl
use strict;
use warnings;
use Foo 'subroutine';
use Bar;
my $arg1 = "blah";
print subroutine($arg1);
print Bar->subroutine($arg1);
output
Ordinary subroutine arg is blah
Class method arg is blah
There's nothing inherently wrong with an ordinary subroutine. They do what they're designed to do very well.
Methods on the other hand, do all the same things and play nicely with any Class that inherits from yours.
So ask yourself:
Are you expecting/permitting/encouraging folks to write Classes that inherit from your module?
Is your module defining a more complex data structure that works well as an object?
or
Is your module a library of utilities that operate on fundamental data types?
There's plenty of room in this world for both, but if you find yourself, as you did in Bar, ignoring $class (or more commonly $self) throughout the module, then perhaps you've gone too far by designing them as methods. More importantly, anyone who tries to inherit from your marginally OO "Class" will get a rude surprise when your methods can't tell the difference between the two classes...
This is more a question of code paradigm.
There is absolutely nothing wrong with a non object oriented approach to your code. It works, and it works well.
However, object orientation provides a bunch of benefits that are worth considering - and if they're something you want, go an OO route.
Specifically - objects provide encapsulation. It makes it a lot easier for me to write a module and you to just use it. Look at say, LWP::UserAgent for an example:
require LWP::UserAgent;
my $ua = LWP::UserAgent->new;
$ua->timeout(10);
$ua->env_proxy;
$ua->agent('Mozilla/5.0');
my $response = $ua->get('http://search.cpan.org/');
if ($response->is_success) {
print $response->decoded_content; # or whatever
}
else {
die $response->status_line;
}
Now, all of the above you could do via inherited subroutines. But if you wanted to do multiple fetches of multiple pages, you'd either have to:
Build a sub that took all the parameters you needed - including returning somehow, a 'success/fail/result' - maybe in an array?
Otherwise have 'state' hidden in your external module.
OO is just a neater, more understandable method of doing that. (There are other benefits of doing OO, which I'm sure you could Google).

Modifications to local perl module not recognized

I have a single perl subroutine in a file of its own. It is called separately by two different perl scripts. I have modified the list of arguments passed in, and made the necessary changes in both calling scripts, but only one script does what I expect. When I use the perl debugger on the other one, when the debugger steps into the subroutine in the module, it shows me the way the module looked before I edited it. So when I run that script, it is passing in the new argument list, but the module is trying to assign them the old way, which clearly is wrong.
What could cause this? Why does one script work correctly and the other one not?
For specifics, yes I'm using strict and warnings.
Old:
use strict;
use warnings;
use lib("/absolute/path/to/module"); #mymodule.pm lives here
use packagename;
my $string = "foo";
my %Hash = my_sub($foo);
and in the module:
package packagename;
use strict;
use warnings;
use Exporter;
use vars qw(#ISA #EXPORT #EXPORT_OK);
#ISA = qw( Exporter );
#EXPORT = qw(my_sub);
#EXPORT_OK = qw(my_sub);
sub my_sub {
my $string = $_[0];
my %Hash;
...
return %Hash;
}
I've added an array reference to the arguments. New to the calling script are:
my #array = qw(Zero One Two);
my %Hash = my_sub(\#array, $string);
New to the module:
sub my_sub {
my (#array) = #{$_[0]};
my $string = $_[1];
}
When I run my script with the debugger and step into this module, it shows my $string being assigned from $_[0] as the first line of the subroutine, just as though I never changed the module.
Again, this only happens with one of my scripts but the other one works fine. Everything is in the same directory. I'm running this on linux, perl 5.10. I'm baffled!
I would guess that the scripts are loading different copies of the module, and you only modified one copy. Try adding
print $INC{'packagename.pm'}."\n";
after the use packagename line in each script. (Don't forget to replace :: with / in packagename, if any.) That will tell you if the scripts are really loading the same module.

How to share/export a global variable between two different perl scripts?

How do we share or export a global variable between two different perl scripts.
Here is the situation:
first.pl
#!/usr/bin/perl
use strict;
our (#a, #b);
.........
second.pl
#!/usr/bin/perl
use strict;
require first.pl;
I want to use global variable (#a, #b) declared in first.pl
Also,suppose there's a variable in second perl file same as first perl file. But I want to use first file's variable. How to achieve this?
In general, when you are working with multiple files, and importing variables or subroutines between them, you will find that requiring files ends up getting a bit complicated as your project grows. This is due to everything sharing a common namespace, but with some variables declared in some files but not others.
The usual way this is resolved in Perl is to create modules, and then import from those modules. In this case:
#!/usr/bin/perl
package My::Module; # saved as My/Module.pm
use strict;
use warnings;
use Exporter;
our #ISA = 'Exporter';
our #EXPORT = qw(#a #b);
our (#a, #b);
#a = 1..3;
#b = "a".."c";
and then to use the module:
#!/usr/bin/perl
use strict;
use warnings;
use My::Module; # imports / declares the two variables
print #a;
print #b;
That use line actually means:
BEGIN {
require "My/Module.pm";
My::Module->import();
}
The import method comes from Exporter. When it is called, it will export the variables in the #EXPORT array into the calling code.
Looking at the documentation for Exporter and perlmod should give you a starting point.
They will share global variables, yes. Are you seeing some problem with that?
Example:
first.pl:
#!/usr/bin/perl
use strict;
use warnings;
our (#a, #b);
#a = 1..3;
#b = "a".."c";
second.pl:
#!/usr/bin/perl
use strict;
use warnings;
require "first.pl";
our (#a,#b);
print #a;
print #b;
Giving:
$ perl second.pl
123abc
Cant you use package and export the variable?

How do I group my package imports into a single custom package?

Normally when I am writing the perl program . I used to include following package .
use strict ;
use warnings ;
use Data::Dumper ;
Now , I want like this, I will not include all this package for every program . for that
I will have these all package in my own package. like following.
my_packages.pm
package my_packages ;
{
use strict ;
use warnings ;
use Data::Dumper;
}
1;
So, that if I add my_packages.pm in perl program , it needs have all above packages .
Actually I have done this experimentation . But I am not able get this things .
which means when I am using my_packages . I am not able get the functionality of "use strict, use warnings , use Data::Dumper ".
Someone help me out of this problem.....
Have a look at ToolSet, which does all the dirty import work for you.
Usage example from pod:
Creating a ToolSet:
# My/Tools.pm
package My::Tools;
use base 'ToolSet';
ToolSet->use_pragma( 'strict' );
ToolSet->use_pragma( 'warnings' );
ToolSet->use_pragma( qw/feature say switch/ ); # perl 5.10
# define exports from other modules
ToolSet->export(
'Carp' => undef, # get the defaults
'Scalar::Util' => 'refaddr', # or a specific list
);
# define exports from this module
our #EXPORT = qw( shout );
sub shout { print uc shift };
1; # modules must return true
Using a ToolSet:
use My::Tools;
# strict is on
# warnings are on
# Carp and refaddr are imported
carp "We can carp!";
print refaddr [];
shout "We can shout, too!";
/I3az/
This is harder than you expect.
For pragmas like strict and warnings you can pass them through.
For modules that don't export functions such as object oriented ones, it will work.
However for modules that export by default, like Data::Dumper (it gives you the Dumper() function in the package of the caller), it is trickier.
You can make it work by telling Exporter that there is an extra layer of magic:
So you could do:
package my_packages;
use strict;
use warnings;
use Data::Dumper;
use IO::Socket;
$Exporter::ExportLevel = 1; # Tell Exporter to export to the caller
sub import {
# Enable this in the callers package
strict->import; # pragma in caller
warnings->import; # pragma in caller
Data::Dumper->import; # Adds Dumper() to caller
# No need for IO::Socket since it's OO.
return 1;
}
1;
For three modules, this hardly seems to be worth it.
See this:
package Foo;
use warnings;
sub import {
warnings->import;
}
1;
And now:
$ perl <<CUT
> use Foo;
> \$a = 5; # backslash just to keep the $ from being eaten by shell
> CUT
Name "main::a" used only once: possible typo at - line 2.
Taken from Modern::Perl.