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

Я сохраняю название подпрограммы, я хочу зайти во время выполнения в переменной, названной $action. Тогда я использую это для вызова этого sub в нужное время:

&{\&{$action}}();

Хорошо работает. Единственная вещь, которую я не люблю, состоит в том, что это ужасно и каждый раз, когда я делаю это, я чувствую себя признательным для добавления комментария для следующего разработчика:

# call the sub by the name of $action

Кто-либо знает более симпатичный способ сделать это?


ОБНОВЛЕНИЕ: идея здесь состояла в том, чтобы избежать необходимости поддерживать таблицу отправки каждый раз, когда я добавил новый вызываемый sub, так как я - единственный разработчик, я не волнуюсь по поводу других программистов после или не после 'правил'. Принесение в жертву небольшого количества безопасности для моего удобства. Вместо этого мой модуль отправки проверил бы $action, чтобы удостовериться, что 1) это - название определенной подпрограммы и не вредоносного кода для выполнения с оценкой и 2) это, это не выполнило бы sub, снабженного предисловием подчеркиванием, которое будет отмечено как внутренние единственные нижние индексы этим соглашением о присвоении имен.

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


ЗАКЛЮЧИТЕЛЬНОЕ ОБНОВЛЕНИЕ: Я думаю, что выбрал таблицу отправки, в конце концов. Хотя мне было бы любопытно, если кто-либо, кто читает этот вопрос, когда-либо пытался покончить один и как они сделали это, я должен поклониться коллективной мудрости здесь. Благодаря всем, многим большим ответам.

57
задан Marcus 17 December 2009 в 11:55
поделиться

7 ответов

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

my %actions = ( foo => \&foo,
                bar => \&bar,
                baz => sub { print 'baz!' } 
                ... 
              );

Затем вы можете легко вызвать нужную:

$actions{$action}->();

Вы можете также добавьте некоторую проверку, чтобы убедиться, что $ action является допустимым ключом в хэше, и т. д.

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

83
ответ дан 24 November 2019 в 19:20
поделиться

Просто & $ action () , но обычно лучше использовать ссылки на коды с самого начала или используйте хеш диспетчера. Например:

my $disp = {foo => \&some_sub, bar => \&some_other_sub };
$disp->{'foo'}->();
21
ответ дан 24 November 2019 в 19:20
поделиться

А? Вы можете просто сказать

    $action->()

Пример:

    sub f { return 11 }
    $action = 'f';
    print $action->();


    $ perl subfromscalar.pl
    11

Конструкции, подобные

    'f'->()     # equivalent to   &f()

, также работают.

16
ответ дан 24 November 2019 в 19:20
поделиться

Я не уверен, что понимаю, что вы имеете в виду. (Я думаю, что это еще один из недавней группы вопросов «Как я могу использовать переменную в качестве имени переменной?», Но, возможно, и нет.)

В любом случае вы должны иметь возможность назначить всю подпрограмму переменной (в качестве справки), а затем назовите его прямо:

# create the $action variable - a reference to the subroutine
my $action = \&preach_it;
# later - perhaps much later - I call it
$action->();

sub preach_it {
    print "Can I get an amen!\n"
}
11
ответ дан 24 November 2019 в 19:20
поделиться

Самое главное: почему вы хотите использовать переменную в качестве имени функции. Что будет, если это будет eval? Есть ли список функций, которые можно использовать? Или это может быть какая-то функция? Если список существует - сколько он?

Как правило, лучший способ справиться с такими случаями - использовать таблицы диспетчеризации:

my %dispatch = (
   'addition' => \&some_addition_function,
   'multiplication' => sub { $self->call_method( @_ ) },
);

А затем просто:

$dispatch{ $your_variable }->( 'any', 'args' );
10
ответ дан 24 November 2019 в 19:20
поделиться

Я делаю нечто подобное. Я разделил его на две строки, чтобы сделать его более узнаваемым, но он не намного красивее.

my $sub = \&{$action};
$sub->();

Я не знаю более правильного или красивого способа сделать это. Как бы то ни было, у нас есть рабочий код, который делает то, что делаете вы, и он работает без отключения use strict .

6
ответ дан 24 November 2019 в 19:20
поделиться

Если это только в одной программе, напишите функцию, которая вызывает подпрограмму, используя имя переменной, и только один раз документировать / извиняться?

0
ответ дан 24 November 2019 в 19:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: