perl - 如何获取被调用的别名子程序的名称?

标签 perl

我怎么知道哪个别名用于调用别名子例程? caller 给出了原始的 sub-name,但我希望看到调用时使用的名称。

例子:

use 5.010;
sub x_y_z {
  return ( caller(0) )[3];
}

*foo_bar_baz = \&x_y_z;

say x_y_z();        # x_y_z
say foo_bar_baz();  # x_y_z, but need foo_bar_baz

编辑以解决 XY 问题

我添加另一个例子来展示我更深层次的意图。我想创建调度表来路由一些任务:

my $dispatch = {
  x => {
    y => {
      z => sub {
          &x_y_z;
      },
    }
  },
  a => {
    b => {
      c => {
        d => sub {
          &a_b_c_d;
        },
      }
    }
  }
}

sub foo {
  my @arg = ( split '_', ( split( '::', ( caller(0) )[3] ) )[1] );  
  return @arg;
}

*x_y_z = \&foo;
*a_b_c_d = \&foo;

正如您想象的那样,这棵树可能会长得很大。现在 dispatch-tree 中的许多叶子都需要基本相同的 sub,它们只是它们被调用(命名)的方式不同,我希望只有一个 sub 并为特定任务取别名。

最佳答案

您尝试做的事情在 Perl 的数据模型中是根本不可能的。别名只是一个别名,而不是一个有自己身份的对象。

请注意,可以复制一个子程序并为其指定一个新名称,例如:

use Sub::Name;

*x_y_z = subname x_y_z => \&foo;

但您必须手动执行此操作。

除了堆栈跟踪之外,依赖子名不是一个好主意。尝试在这些名称之上构建任何逻辑可能会导致难以调试的困惑,而不是优雅的软件。

最好将路由名称作为显式参数传递到处理程序函数,并创建一个辅助函数来抽象必要的管道。例如:

my %routes;

sub route {
  my ($name, $handler) = @_;
  $routes{$name} = sub { $handler->($name => @_) };
  return;
}

sub common_handler { ... }

route a_b_c => \&common_handler;
route x_y_z => \&common_handler;
route foo_bar => sub {
  my ($route) = @_;
  say "Custom handler invoked for route $route";
};

$routes{$name}->(@args);

如果绝对必要,您当然可以实现这样的 route 函数,以便它将处理程序安装为命名子例程。但那时你正在构建某种框架,如 Moo(se),而不是普通的 Perl 模块。

关于perl - 如何获取被调用的别名子程序的名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51310313/

相关文章:

perl - 如何让 Mojolicious 处理 UTF-8?

regex - 仅当 $1 < $2 时,我怎样才能让我的 Perl 正则表达式匹配?

java - 用于事件的 Facebook SDK

perl - 如何在 Perl 中检查数组的所有元素是否相同?

php - PHP 使用的 OS X 和 OpenSSL 上的 Composer 错误

perl - Perl的postfix `for`语法在哪里记录?

Perl 自定义排序

c - perlbench 在 SPEC 2006 线束之外导致段错误

perl - 教程点.com : Perl - Formats: Scalar found where operator expected

perl - 如何使用Perl的 'Digest::CRC'模块计算DNP3 CRC