How do you create a callback function (dispatch table) in Perl using hashes?

qodeninja picture qodeninja · Aug 30, 2011 · Viewed 10.2k times · Source

I want to call a main controller function that dispatches other function dynamically, something like this:

package Controller;

my %callback_funcs = ();

sub register_callback{
   my ($class,$callback,$options) = _@;
   #apppend to %callback_funcs hash ... ?
}

sub main{
%callback_funcs = ( add => 'add_func', rem => 'remove_func', edit => 'edit_func');  
  while(<STDIN>){
     last if ($_ =~ /^\s*$/);
     if($_ == 'add' || _$ == 'rem' || _$ == 'edit'){
        $result = ${callback_funcs['add']['func']}(callback_funcs['add']['options']);
     }
  }
}

sub add_func{
...
}

One caveat is that the subs are defined in other Modules, so the callbacks would have to be able to reference them... plus I'm having a hard time getting the hashes right!

Answer

masonk picture masonk · Aug 30, 2011

So, it's possible to have a hash that contains anonymous subroutines that you can invoke from stdin.

my %callbacks = (
    add => sub {
        # do stuff
    },
    fuzzerbligh => sub {
        # other stuff
    },
);

And you can insert more hashvalues into the hash:

$callbacks{next} = sub {
    ...
};

And you would invoke one like this

$callbacks{next}->(@args);

Or

my $coderef = $callbacks{next};
$coderef->(@args);

You can get the hashkey from STDIN, or anywhere else.

You can also define them nonymously and then take a reference to them.

sub delete {
    # regular sub definition
}

$callbacks{delete} = \&delete;

I wouldn't call these callbacks, however. Callbacks are subs that get called after another subroutine has returned.

Your code is also rife with syntax errors which may be obscuring the deeper issues here. It's also not clear to me what you're trying to do with the second level of arrays. When are you defining these subs, and who is using them when, and for what?