如何优雅地调用名称保存在变量中的 Perl 子例程? [英] How can I elegantly call a Perl subroutine whose name is held in a variable?

查看:30
本文介绍了如何优雅地调用名称保存在变量中的 Perl 子例程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将要在运行时调用的子例程的名称保存在名为 $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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆