mlong has asked for the wisdom of the Perl Monks concerning the following question:

In this recipe from the Cookbook, I see how to store a reference to a fuction: http://eda.ee.nctu.edu.tw/~zephlin/O'Reilly/books/perl2/cookbook/ch11_05.htm

What I am trying to do, however, is to create a hash whose keys point to method (function) references of an object instance. Here's what it looks like currently.
$md_config->{"[cust_num]"} = \&{$web_services->GetCustomerNumber}; $md_config->{"[description]"} = \&{$web_services->GetCustomerDescripti +on};
$web_services is the object instance. The syntax seems acceptable to perl, but when I go to get the method later to run it like this:
$this->{md_config}->{"cust_num"}->();
It comes back with the error: "Undefined subroutine &MDScriptConfig:cust29435 called at MDScriptConfig.pm line 20."

What's interesting is that 'cust29435' that you see in the error message is the result of running the function pointed to in the hash. Which means it's actually working--soft of. Perl is trying to interpret the function result as a function name rather that the actual value that I'm wanting. Anyhow, I would appreciate any help you can provide.

Thanks.

-Matt

Replies are listed 'Best First'.
Re: Storing/Calling References to Instance Methods
by merlyn (Sage) on Sep 20, 2007 at 16:13 UTC
    You need to create a closure instead:
    $md_config->{"[cust_num]"} = sub { $web_services->GetCustomerNumber(@_ +) };
    That puts one extra subroutine call on the stack though. If you have anything that is stack-sensitive (calls caller, for example), you'll need to use a goto to get rid of that extra hop:
    $md_config->{"[cust_num]"} = do { my $meth = $web_services->can("GetCustomerNumber"); sub { unshift @_, $web_services; goto &$meth; } };
      Thanks merlyn. You are the man!

      For a minute I thought I had maybe stumbled upon a way to obtain the value the pointed to function returns by just accessing it via the $obj->{$key} deref mechanism. That would be cool. I don't suppose that is actually possible is it?

      Thanks again.

      -Matt
        You could create a tied hash where $tied{$key} calls the "Get" function. But i think that would just obfuscate in this situation.
Re: Storing/Calling References to Instance Methods
by ikegami (Patriarch) on Sep 20, 2007 at 16:33 UTC
    If the LHS of -> is always $web_services, you could do the following:
    $md_config->{cust_num } = 'GetCustomerNumber'; $md_config->{description} = 'GetCustomerDescription'; my $field = 'cust_num'; my $meth = $md_config->{$field} or die("Unknown field $field\n"); $web_services->$meth();
      Now that's an interesting idea. I will give that a try.

      Thank you.

      -Matt