如何优雅地调用名称保存在变量中的Perl子例程? [英] How can I elegantly call a Perl subroutine whose name is held in a variable?
问题描述
我将要在运行时调用的子例程的名称保留在名为$ action的变量中.然后,我用它在正确的时间调用该子程序:
I keep the name of the subroutine I want to call at runtime in a variable called $action. Then I use this to call that sub at the right time:
&{\&{$action}}();
工作正常.我唯一不喜欢的是它很丑陋,每次我这样做时,我都会为下一个开发人员添加评论:
Works fine. The only thing I don't like is that it's ugly and every time I do it, I feel beholden to add a comment for the next developer:
# call the sub by the name of $action
有人知道更漂亮的方法吗?
Anyone know a prettier way of doing this?
更新:这里的想法是避免每次我添加一个新的可调用子程序时都必须维护一个调度表,因为我是唯一的开发人员,所以我不担心其他程序员遵循或不遵循规则".为了我的方便,牺牲一点安全性.相反,我的调度模块将检查$ action以确保1)它是已定义的子例程的名称,而不是与eval一起运行的恶意代码,以及2)它不会运行任何带下划线开头的子例程,这将是以此命名约定标记为仅供内部使用的字幕.
UPDATE: The idea here was to avoid having to maintain a dispatch table every time I added a new callable sub, since I am the sole developer, I'm not worried about other programmers following or not following the 'rules'. Sacrificing a bit of security for my convenience. Instead my dispatch module would check $action to make sure that 1) it is the name of a defined subroutine and not malicious code to run with eval, and 2) that it wouldn't run any sub prefaced by an underscore, which would be marked as internal-only subs by this naming convention.
对这种方法有何想法?我将一直忘记将调度表中的子例程列入白名单,我的客户宁愿我在它起作用"方面而不是它是邪恶的安全性"方面犯错. (非常有限的时间来开发应用)
Any thoughts on this approach? Whitelisting subroutines in the dispatch table is something I will forget all the time, and my clients would rather me err on the side of "it works" than "it's wicked secure". (very limited time to develop apps)
最终更新:我想我毕竟已经决定了派遣表.尽管我很想知道读过这个问题的人是否曾经尝试过放弃它,以及他们是如何做到的,但我不得不在这里向集体的智慧鞠躬.感谢所有人,做出了许多出色的回应.
FINAL UPDATE: I think I've decided on a dispatch table after all. Although I'd be curious if anyone who reads this question has ever tried to do away with one and how they did it, I have to bow to the collective wisdom here. Thanks to all, many great responses.
推荐答案
与其将子例程名称存储在变量中并对其进行调用,一种更好的方法是使用子例程引用的哈希(否则称为分发表.)
Rather than storing subroutine names in a variable and calling them, a better way to do this is to use a hash of subroutine references (otherwise known as a dispatch table.)
my %actions = ( foo => \&foo,
bar => \&bar,
baz => sub { print 'baz!' }
...
);
然后,您可以轻松拨打正确的电话:
Then you can call the right one easily:
$actions{$action}->();
您还可以添加一些检查以确保$action
是哈希中的有效密钥,依此类推.
You can also add some checking to make sure $action
is a valid key in the hash, and so forth.
通常,应避免使用符号引用(您现在正在做什么),因为它们会引起各种问题.此外,在打开strict
的情况下,使用真实的子例程引用也可以使用.
In general, you should avoid symbolic references (what you're doing now) as they cause all kinds of problems. In addition, using real subroutine references will work with strict
turned on.
这篇关于如何优雅地调用名称保存在变量中的Perl子例程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!