user3214392
user3214392

Reputation: 255

Getting wrong argument value when trying to call a subroutine using PackageName::ModuleName->subroutine("xyz")in perl

When trying to call a subroutine (defined in a user defined module) in other perl file, getting wrong argument value

#moduleName.pm

package PackageName::moduleName;
use strict;
use warnings;
use base 'Exporter';

sub callMe{
    my($readArg)=(@_);
    print $readArg;
 }


#test.pl

use strict;
use warnings;
use FindBin;                 # locate this script
use lib 'path to parent directory';  # use the parent directory
use PackageName::moduleName;

if( my $temp=PackageName::moduleName->callMe("test")){
    print" True : $temp\n";
}

The function prints value of $temp as : PackageName::moduleName

Not able to figure out why.

P.S. I have to maintain same convention while calling the subroutine

Upvotes: 1

Views: 51

Answers (2)

Sobrique
Sobrique

Reputation: 53488

Because of the way you're calling it via ->.

When you do this, perl passes extra arguments, so you can make a constructor (new).

E.g.

 my $thing = Package::Module -> new(); 

The first argument passed is the class, so you can use that for a bless. See: perlootut

E.g.

sub new { 
    my ( $class, @args ) = @_;
    my $self = {};
    bless ( $self, $class ); 
}

This also applies when you call an instantiated object:

$thing -> do_something(); 

It passes a reference to $self as the first argument.

sub do_something { 
    my ( $self, @args ) = @_;
    print "Got args of @args\n";
    $self -> {firstarg} = shift ( @args ); 
}

If you want to do that, try instead:

PackageName::ModuleName::callMe("test"); 

Upvotes: 1

simbabque
simbabque

Reputation: 54333

You are calling a function as a class method with Foo::Bar->frobnicate(@args). In that case, Perl will do the following things because of the arrow ->:

  • check what's on the left of the arrow
    • if it's blessed, find the package (e.g. $q is package CGI)
    • if it's not blessed, assume it's a package (e.g. Foo::Bar)
  • within that package namespace, find a sub with the name on the right of the arrow (e.g. frobnicate)
  • call that sub and pass what's on the left of the arrow as the first argument

Now it looks like this:

Foo::Bar::frobnicate('Foo::Bar', @args);

In frobnicate, you have to deal with that:

sub frobnicate {
  my ($class, @args) = @_;
  # ...
}

That's typically done in a new, which is the most likely use of a class method.

If you don't want to deal with it, call the sub directly in its namespace, and not with the arrow notation.

my $rv = Foo::Bar::frobnicate(@args);

Upvotes: 3

Related Questions