tags:

views:

49

answers:

1

Let us say if I have a Perl module Resounces.pm with this code snippet

my $my_class = new MY_CLASS;
our resource => { '/list' => $my_class->list_files() };

So can I call this resource variable in another perl script something similar like this?

use Resources;
$Resources::resource->{'/list'};

My intention is to execute list_files() method when I use that last statement. Is that even possible?

+1  A: 

One option is to use an anonymous sub:

package Resources;
my $my_class = new MY_CLASS;
our $resource = { '/list' => sub { $my_class->list_files(@_); } };

...

package main;
# dereference the code ref
&{$Resources::resource->{'/list'}};
# or call it:
$Resources::resource->{'/list'}();

Should you change what $my_class references, it will also be changed in the anonymous function. This may be what you want; if not, keep reading for a function (bindMethod) that binds an object and a method.

If you don't want the anonymous function to appear on the stack:

our $resource = { '/list' => sub { unshift @_, $my_class; 
                                   goto &MyClass::list_files; } };

Note that this form of goto isn't the usual goto statement—it's a tail call.

You could define a helper method to set up the binding, though honestly it doesn't gain you much.

sub bindMethod {
    my ($obj, $meth) = @_;
    return sub { unshift @_, $obj; goto &{$meth}; }
}

my $my_class = new MyClass;
our $resource = { '/list' => bindMethod($my_class, \&MyClass::list_files) };

Here's a version of bindMethod that doesn't require the class to be specified with the method name.

sub bindMethod {
    my ($obj, $meth) = @_;
    if (! ref $meth) {
        my $class = ref $obj;
        $meth = \&{"${class}::$meth"};
    }
    return sub { unshift @_, $obj; goto &{$meth}; }
}
...
my $my_class = new MyClass;
our $resource = { '/list' => bindMethod($my_class, 'list_files') };
outis
That is exactly what I was looking for. Thank you.
John
@John: make sure you use the updated version. The old one failed to pass arguments to the wrapped method.
outis
Thank you again. I learned something new today - tail call.
John