November 19, 2009

Transparently handle first argument to Perl Package subroutines

Filed under: Perl, Programming — morgan @ 16:11

It’s always baffled me that Perl subroutines behave differently when called from inside the Package vs. outside.

The use case may be obvious but I’ll say it: you write a small utility routine that you want to call as $pack->func(1); and from within the Package as func(1);;

The problem of course is that when called as $pack->func(1); the first arg will the object itself and when called as func(1); from within the package the first arg will be “1.”

There’s a very simple solution:
shift if ((ref $_[0]) eq __PACKAGE__);

Here’s a simple example:


#!/usr/bin/perl -w
#
package Pack;

sub new {
    my $c = shift;

    my $self = {};
    bless $self, $c;
    return $self;
}

sub func {
    shift if ((ref $_[0]) eq __PACKAGE__);
    my $a = shift;

    print "passed in: $a\n";
}

sub call_func {
    print "calling func from inside ", __PACKAGE__, ":\n";
    func(2);
}
1;

my $p = new Pack;

print "calling func from main:\n";
$p->func(1);

$p->call_func();

Try commenting the “shift” line in sub func() and see how it behaves differently.

Powered by WordPress