【问题标题】:Anonymous subroutines/subroutine references stored in data structures存储在数据结构中的匿名子程序/子程序引用
【发布时间】:2013-05-13 23:45:06
【问题描述】:

Why would I use Perl anonymous subroutines instead of a named one? 启发我思考以下优点:

  • 在数组、散列和标量中存储匿名子。

这是一个非常酷的概念,但它是否实用?有什么理由我必须使用存储在某种数据结构中的匿名子/子引用?或者可能是一种方便的情况?

我理解为什么在某些情况下需要匿名 subs,例如处理共享变量(当匿名 sub 在另一个 sub 中声明时),但除非我遗漏了什么,否则我只是看不出使用任何某种功能参考。似乎我们应该直接调用函数,代码看起来会更好/更有条理。

请告诉我我错了。我很想有充分的理由使用这些东西。

提前致谢。

【问题讨论】:

  • 查看调度表的概念。 en.wikipedia.org/wiki/Dispatch_table
  • 嗯,符号表基本上是一个巨大的 HoH(任意深度),它包含对每个命名子的引用。这只是众多用途之一。
  • @ikegami 难道有些语言在函数中也使用它来进行闭包以便跟踪程序状态吗?
  • Perl 是解释的,不是编译的,对吧?那么后期绑定有什么好处呢?我看到调度表的示例是在 perl 中,但有什么意义呢?
  • 分派表的意义在于,它可以让您轻松避免一堆凌乱的 if/elsif/elsif 语句。它简化了动态规则集而不是硬编码逻辑。它灵活且重量轻。阅读高阶 Perl (hop.perl.plover.com),然后问有什么意义。

标签: perl perl-data-structures


【解决方案1】:

调度表对于根据某个值动态确定要采取的步骤很有用:

my %disp = (
   foo => sub { 'foo' },
   bar => sub { 'bar' },
);

my $cmd = get_cmd_somehow();
if (defined $disp{$cmd}) {
  $disp{$cmd}->(@args)
} else {
  die "I don't know how to handle $cmd"
}

(方法派发 via ->can($method) 在概念上类似,但更灵活,细节隐藏。)

匿名函数和词法闭包还有许多其他用途;也许更深入地研究“高阶函数”。 (例如考虑 map()/grep()。)

【讨论】:

  • 调度不是使用匿名子例程的解释。您可以使用普通的命名子程序实现相同的效果:my %disp = ( foo => \&disp_foo, bar => \&disp_bar );
  • 是的,也解决了问题的第二部分,关于存储在数据结构中的子引用。
【解决方案2】:

面向对象的方法非常类似于匿名子例程。多态性意味着对象的方法可以更改,而无需调用代码手动进行查找以查看要运行的例程。这非常有用。

另外,想想 perl 的排序。为什么要为简单的排序方法设置命名例程?同上 map 和 grep。

同样,迭代器也非常有用。另外,考虑存储一个以后可以解析的例程,而不是只能存储一个静态值。

最后,如果您不想存储匿名例程(甚至对例程的引用),那是您的事。但有选择总比没有好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多