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

perl – 使用Sub :: Quote弱化捕获

发布时间:2020-12-15 21:44:36 所属栏目:大数据 来源:网络整理
导读:我想削弱 Sub::Quote生成的代码中的捕获变量.例如,这里是未引用的替代方法: use 5.10.0;use Scalar::Util qw[ weaken ];{ my $s = 'foo'; my $x = sub { say $s }; weaken( my $y = $x ); my $bar = sub { $y }; $bar; $x = undef; $bar} 和输出: fooCan't
我想削弱 Sub::Quote生成的代码中的捕获变量.例如,这里是未引用的替代方法:
use 5.10.0;
use Scalar::Util qw[ weaken ];
{
  my $s = 'foo';
  my $x = sub { say $s };
  weaken( my $y = $x );

  my $bar = sub { &$y };
  &$bar;
  $x = undef;
  &$bar
}

和输出:

foo
Can't use an undefined value as a subroutine reference [...]

这是我的Sub :: Quote尝试:

use 5.10.0;
use Sub::Quote;
use Scalar::Util qw[ weaken ];
{
  my $s = 'foo';
  my $x = sub { say $s };
  weaken( my $y = $x );

  my $bar = quote_sub( '&$y',{ '$y' => $y } );
  &$bar;
  $x = undef;
  &$bar;
}

和输出:

foo
foo

显然,被捕获的$y并未被削弱.有没有办法改变生成的代码来削弱捕获的变量?

文档很稀疏,Sub :: Quote实现很复杂;我相信当前的代码是不可能的,但我希望被证明是错的.

解决方法

my $bar = quote_sub( '&$y',{ '$y' => $y } );

大致相同

my $bar = eval(q{ my $y = $y; sub { &$y } });

(它做得更多,但这些位与这个问题无关).如您所见,这为sub [1]创建了一个新的强引用.

作为一种解决方法,您可以添加一个间接层:

my $bar = eval(q{ my $y_ref = $y; sub { &{ $$y_ref } } });

这可以通过使用:

my $bar = quote_sub( '&{$$y_ref}',{ '$y_ref' => $y } );

如果Sub :: Quote创建的$y是$y的别名,则不会有任何问题.这可以使用Data :: Alias或5.22中引入的实验性功能来实现.

这可以通过以下方式证明:

{
  package Sub::Quote;

  my $sub = sub {
    my ($from,$captures,$indent) = @_;
    join(
      '',"use feature qw( refaliasing );n","no warnings qw( experimental::refaliasing );n",map {
        /^([@%$])/
          or croak "capture key should start with @,% or $: $_";
        (' ' x $indent).qq{my ${_} = ${1}{${from}->{${quotify $_}}};n};
      } keys %$captures
    )
  };

  no warnings qw( redefine );
  *capture_unroll = $sub;
}


my $bar = quote_sub( '&$y',{ '$y' => $y } );

您可以与模块的维护者讨论添加一个会导致使用别名的选项.

>当您创建(强或弱)引用的副本时,它是一个强大的参考.

(编辑:李大同)

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

    推荐文章
      热点阅读