views:

83

answers:

2
$ cat test.pl
use strict;
use warnings;

sub route {
    print "hello, world!";
}

my %h;
$h{'a'} = 'route';

print "1\n";
$h{a};

print "2\n";
$h{a}();

print "3\n";
"$h{a}".();
$ perl test.pl
Useless use of hash element in void context at test.pl line 12.
Useless use of concatenation (.) or string in void context at test.pl line 18.
1
2
Can't use string ("route") as a subroutine ref while "strict refs" in use at test.pl line 15.
$

What is the right way to call route()?

+10  A: 

You're trying to use $h{a} as a symbol reference. And that's explicitly disallowed by "use strict". If you turn off strict mode, then you can do it like this:

no strict;
&{$h{a}};

But the best approach is to store a "real" reference to the subroutine in your hash.

#!/usr/bin/perl

use strict;
use warnings;

sub route {
    print "hello, world!";
}

my %h;
$h{a} = \&route;

$h{a}->();
davorg
While I completely agree with davorg's suggestion of using code references, I also want to point out perl's `can` feature. Given the name of the package a function lives in and the function name itself, it can retrieve the code reference for that function using `$package->can($function)`, without having to turn strict refs off.
rafl
`no strict 'refs'` is enough.
dolmen
A: 

You have to dereference the string containing the routine name as a sub. The parenthesis are optional.

my $name = 'route';
&{$name};

As your routine name is a hash value, you have to extract it from the hash. Also as you are using strict (which is a good practice), you have to locally disable checks.

{
    no strict 'refs';
    &{$h{a}};
}

However, as davorg suggested in his answer, it would be better (performance-wise) to directly store a reference to the sub in your hash, instead of the routine name.

dolmen