Reputation: 6863
I have a perl mason file and one of the lines looks like this:
$result = PI::Membership::Service->cancel(name => $name)
What exactly does that mean? Is it calling another module? Is it object oriented perl code?
Thanks
Upvotes: 0
Views: 692
Reputation: 107090
Unless $result
is a Pi::Membership::Service
object, it's not really an object oriented call because it's neither creating or manipulating an object. An object oriented call would look like this:
my $obj = Foo::Bar->new; #Creating an object of class `Foo::Bar`
$obj->Baz #Calling method "Baz" on object "$obj";
It looks like this is an object style call to access a subroutine that's in another package and has not been exported.
To understand what's really going on, you must know about namespaces. Perl uses namespaces. Most of the time you might not be aware of it because you are using the default namespace of main
. Namespaces are needed because you could end up (especially in pre-4.x versions of Perl) function and variable name collisions. Here's a program I have written in the old Perl 3.x style:
require "fribulate.pl";
$value = 4.5;
$new_value = fribulate($value);
print "Fribulated Value = $new_value Original value = $value\n";
And here's my fribulate.pl
program:
sub fribulate {
my $param = shift;
$value = $param * 2;
return $value * 6;
}
1;
When I run my program, I get:
Fribulated Value = 54. Original Value = 9
Wait? Wasn't it originally 4.5? The fribulate.pl
program affected my $value
because it is also using a variable called $value
. To get around this, Perl created the package
command that creates a new namespace:
package Fribulate;
sub fribulate {
my $param = shift;
$value = $param * 2;
return $value * 3.1416;
}
1;
Now, the fribulate.pl
program is not in namespace main
, but in namespace Fribulate
. Thus, the $value
variable used in fribulate.pl
isn't the same as my $value
variable.
However, I can access a variable in another namespace if I prepend the namespace on it:
require "fribulate.pl";
$value = 4.5;
$new_value = fribulate($value);
print "Fribulated Value = $new_value Original value = $value\n";
# Printing the value of $value from frimbulate.pl:
print "And in fribulate.pl, it's using $Fribulate::value\n";
You would have seen this if you used File:Find. To access the full name of a file, you use $File::Find::name
. To access the file's directory, you use $File::Find::dir
. The namespace File::Find
is being prepended to the $dir
and $name
variables in File::Find
.
The problem with namespaces is that everything is now in the new namespace, including my frimbulate
function in frimbulate.pl
. Thus, my original program also has to prepend the namespace in front of the function in order to work:
require "fribulate.pl";
$value = 4.5;
$new_value = Frimbulate::fribulate($value);
print "Fribulated Value = $new_value Original value = $value\n";
To get around this issue, you did a little fancy footwork in the frimbulate.pl
program:
Package Frimbulate;
require Exporter;
@EXPORT = qw(frimbulate);
sub fribulate {
my $param = shift;
$value = $param * 2;
return $value * 3.1416;
}
1;
The Exporter
package sprinkles magic pixie dust1 on the functions in @EXPORT
and makes them available into the main
namespace -- the default namespace where all of your stuff resides. Thus, modules like File::Copy and File::Basename use Exporter
to allow you to access their respective copy
and basename
subroutines without prepending the package name in front of them.
This is now considered bad style because you could end up overwriting other subroutines with the same name without any warning. In the new style of writing modules, you no longer automatically export all of your functions in the @EXPORT
array. You'll notice this in File::Path which doesn't automatically export its functions into the main
namespace without our explicitly requesting it. Instead, you put them in @EXPORT_OK
which requires users to ask them to be pushed into the namespace:
Package Frimbulate;
require Exporter;
@EXPORT_OK = qw(frimbulate); #You have to request the frimbulate subroutine
sub fribulate {
my $param = shift;
$value = $param * 2;
return $value * 3.1416;
}
1;
# Now I have to ask that the frimbulate subroutine be import into my main namespace
require "fribulate.pl" qw(frimbulate);
$value = 4.5;
$new_value = fribulate($value);
print "Fribulated Value = $new_value Original value = $value\n";
This should now give you enough background to read the Perl Module documentation and quite possibly understand what's going on. The Perlmod documentation covers namespaces, the symbol table, and even a bit about variable scope. It's contains a lot of information, and can be a bit intimidating without basic information.
1 No pixies were harmed in use of the Exporter module. If you look at Exporter.pm
which you can find with the perldoc -l Exporter
command, you'll see that it's directly manipulating the symbol table.
Upvotes: 1
Reputation: 118685
It is calling (invoking) the subroutine PI::Membership::Service::cancel
with three arguments.
"PI::Membership::Service"
"name"
$name
Given normal naming conventions, this is calling a subroutine called cancel
in the package PI::Membership::Service
, defined in a file named PI/Membership/Service.pm
somewhere along your @INC
path (there are many abnormal naming conventions, however, so there is no guarantee you will find such a file). And if the PI::Membership::Service
package (class) inherits from one or more other packages, the cancel
subroutine might actually be defined in one of those packages.
More details in perlobj
.
Upvotes: 7