Я сохраняю название подпрограммы, я хочу зайти во время выполнения в переменной, названной $action. Тогда я использую это для вызова этого sub в нужное время:
&{\&{$action}}();
Хорошо работает. Единственная вещь, которую я не люблю, состоит в том, что это ужасно и каждый раз, когда я делаю это, я чувствую себя признательным для добавления комментария для следующего разработчика:
# call the sub by the name of $action
Кто-либо знает более симпатичный способ сделать это?
ОБНОВЛЕНИЕ: идея здесь состояла в том, чтобы избежать необходимости поддерживать таблицу отправки каждый раз, когда я добавил новый вызываемый sub, так как я - единственный разработчик, я не волнуюсь по поводу других программистов после или не после 'правил'. Принесение в жертву небольшого количества безопасности для моего удобства. Вместо этого мой модуль отправки проверил бы $action, чтобы удостовериться, что 1) это - название определенной подпрограммы и не вредоносного кода для выполнения с оценкой и 2) это, это не выполнило бы sub, снабженного предисловием подчеркиванием, которое будет отмечено как внутренние единственные нижние индексы этим соглашением о присвоении имен.
Какие-либо мысли об этом подходе? Белый список подпрограмм в таблице отправки является чем-то, что я забуду все время, и мои клиенты быть бы меня допускать ошибку на стороне "его, работает", чем "это злое безопасный". (очень ограниченное время для разработки приложений)
ЗАКЛЮЧИТЕЛЬНОЕ ОБНОВЛЕНИЕ: Я думаю, что выбрал таблицу отправки, в конце концов. Хотя мне было бы любопытно, если кто-либо, кто читает этот вопрос, когда-либо пытался покончить один и как они сделали это, я должен поклониться коллективной мудрости здесь. Благодаря всем, многим большим ответам.
вместо того, чтобы сохранять имена подпрограмм в переменной и вызывая их, лучший способ сделать это - использовать хэш ссылок на подпрограммы (также известный как диспетчерская таблица .)
my %actions = ( foo => \&foo,
bar => \&bar,
baz => sub { print 'baz!' }
...
);
Затем вы можете легко вызвать нужную:
$actions{$action}->();
Вы можете также добавьте некоторую проверку, чтобы убедиться, что $ action
является допустимым ключом в хэше, и т. д.
В общем, вам следует избегать символических ссылок (то, что вы делаете сейчас), поскольку они вызывают все виды проблем. Кроме того, использование реальных ссылок на подпрограммы будет работать с включенным strict
.
Просто & $ action ()
, но обычно лучше использовать ссылки на коды с самого начала или используйте хеш диспетчера. Например:
my $disp = {foo => \&some_sub, bar => \&some_other_sub };
$disp->{'foo'}->();
А? Вы можете просто сказать
$action->()
Пример:
sub f { return 11 }
$action = 'f';
print $action->();
$ perl subfromscalar.pl
11
Конструкции, подобные
'f'->() # equivalent to &f()
, также работают.
Я не уверен, что понимаю, что вы имеете в виду. (Я думаю, что это еще один из недавней группы вопросов «Как я могу использовать переменную в качестве имени переменной?», Но, возможно, и нет.)
В любом случае вы должны иметь возможность назначить всю подпрограмму переменной (в качестве справки), а затем назовите его прямо:
# 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"
}
Самое главное: почему вы хотите использовать переменную в качестве имени функции. Что будет, если это будет eval? Есть ли список функций, которые можно использовать? Или это может быть какая-то функция? Если список существует - сколько он?
Как правило, лучший способ справиться с такими случаями - использовать таблицы диспетчеризации:
my %dispatch = (
'addition' => \&some_addition_function,
'multiplication' => sub { $self->call_method( @_ ) },
);
А затем просто:
$dispatch{ $your_variable }->( 'any', 'args' );
Я делаю нечто подобное. Я разделил его на две строки, чтобы сделать его более узнаваемым, но он не намного красивее.
my $sub = \&{$action};
$sub->();
Я не знаю более правильного или красивого способа сделать это. Как бы то ни было, у нас есть рабочий код, который делает то, что делаете вы, и он работает без отключения use strict
.
Если это только в одной программе, напишите функцию, которая вызывает подпрограмму, используя имя переменной, и только один раз документировать / извиняться?