Как в Perl вызвать подпрограмму, имя которой является значением хеша?

$ 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.
$

Как правильно позвонить route()?


person Lazer    schedule 01.10.2010    source источник
comment
возможный дубликат Как мне вызвать имя функции, которое хранится в хеш-коде Perl?   -  person Ether    schedule 01.10.2010


Ответы (2)


Вы пытаетесь использовать $ h {a} в качестве ссылки на символ. И это явно запрещено с помощью "строгого использования". Если отключить строгий режим, то сделать это можно так:

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

Но лучший подход - сохранить «настоящую» ссылку на подпрограмму в вашем хэше.

#!/usr/bin/perl

use strict;
use warnings;

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

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

$h{a}->();
person Dave Cross    schedule 01.10.2010
comment
Хотя я полностью согласен с предложением davorg об использовании ссылок на код, я также хочу указать на функцию perl can. Учитывая имя пакета, в котором находится функция, и само имя функции, она может получить ссылку на код для этой функции, используя $package->can($function), без необходимости отключать строгие ссылки. - person rafl; 01.10.2010
comment
no strict 'refs' достаточно. - person dolmen; 01.10.2010

Вы должны разыменовать строку, содержащую имя подпрограммы, как подпрограмму. Скобки необязательны.

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

Поскольку ваше обычное имя представляет собой хеш-значение, вы должны извлечь его из хеш-значения. Кроме того, поскольку вы используете strict (что является хорошей практикой), вам необходимо локально отключить проверки.

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

Однако, как предложил Даворг в своем ответе, было бы лучше (с точки зрения производительности) напрямую хранить ссылку на подпрограмму в вашем хэше, а не на имя подпрограммы.

person dolmen    schedule 01.10.2010