加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

在Perl中,确定coderef包的最可靠方法是什么?

发布时间:2020-12-15 22:01:48 所属栏目:大数据 来源:网络整理
导读:我有一些更高阶的效用函数,它接收代码引用并将该代码应用于某些数据.这些功能中的一些需要在执行子程序期间对变量进行本地化.开始时,我正在使用调用者来确定哪个包本地化,以与本示例中所示相似的方式减少功能: sub reduce (@) { my $code = shift; my $call
我有一些更高阶的效用函数,它接收代码引用并将该代码应用于某些数据.这些功能中的一些需要在执行子程序期间对变量进行本地化.开始时,我正在使用调用者来确定哪个包本地化,以与本示例中所示相似的方式减少功能:
sub reduce (&@) {
    my $code      = shift;
    my $caller    = caller;
    my ($ca,$cb) = do {
        no strict 'refs';
        map *{$caller.'::'.$_} => qw(a b)
    };
    local (*a,*b) = local (*$ca,*$cb);
    $a = shift;
    while (@_) {
        $b = shift;
        $a = $code->()
    }
    $a
}

最初,这种技术工作正常,但是一旦我尝试在高阶函数周围编写一个包装函数,找出正确的调用者就变得复杂了.

sub reduce_ref (&$) {&reduce($_[0],@{$_[1]})}

现在为了减少工作,我需要一些像:

my ($ca,$cb) = do {
        my $caller = 0;
        $caller++ while caller($caller) =~ /^This::Package/;
        no strict 'refs';
        map *{caller($caller).'::'.$_} => qw(a b)
    };

在这一点上,它成为一个跳过的包的问题,??结合从不使用这些包中的功能的纪律.必须有一个更好的方法.

事实证明,高阶函数作为参数的子例程包含足够的元数据来解决问题.我目前的解决方案是使用B内省模块来确定传??入子程序的编译存储空间.这样,无论代码编译和执行之间发生什么,高阶函数总是知道正确的包进行本地化.

my ($ca,$cb) = do {
        require B;
        my $caller = B::svref_2object($code)->STASH->NAME;
        no strict 'refs';
        map *{$caller.'::'.$_} => qw(a b)
    };

所以我的最终问题是,这是否是在这种情况下确定主叫方的最佳方法?还有其他一些我没想到的方法吗?目前的解决方案是否有等待发生的BUG?

解决方法

首先,您可以使用以下内容,不需要任何更改:
sub reduce_ref (&$) { @_ = ( $_[0],@{$_[1]} ); goto &reduce; }

但一般来说,以下确实是你想要的:

B::svref_2object($code)->STASH->NAME

你想要$a和$b变量的子的__PACKAGE__,所以你想知道该子的__PACKAGE__,这正是返回的.它甚至修复了以下内容:

{
   package Utils;
   sub mk_some_reducer {
      ...
      return sub { ... $a ... $b ... };
   }
}

reduce(mk_some_reducer(...),...)

它不会修复所有内容,但是如果不使用参数而不是使用$a和$b,这是不可能的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读