sub get_branch_function { my $query = shift; # get all three levels of keys into variables, # setting defaults as necessary: my $action = $query->param('action') ? $query->param('action') : 'default'; my $confirm = $query->param('confirm') ? 'confirm' : 'default'; my $commit = $query->param('commit') ? 'commit' : 'default'; # set up the hash so that whatever combination of keys # it gets, it will produce a value: my %dispatch = ( add => { confirm => { commit => \&commit_dialog, default => \&add_dialog, }, default => { commit => \&add_dialog, default => \&add_dialog, }, }, remove => { confirm => { commit => \&commit_dialog, default => \&confirm_dialog, }, default => { commit => \&choose_dialog, default => \&choose_dialog, }, }, modify => { confirm => { commit => \&commit_dialog, default => \&confirm_dialog, }, default => { commit => \&choose_dialog, default => \&choose_dialog, }, }, default => { confirm => { commit => \&action_dialog, default => \&action_dialog, }, default => { commit => \&action_dialog, default => \&action_dialog, }, }, ); # now one step should return the right subroutine: return $dispatch{ $action }{ $confirm }{ $default }; }