Perl尽可能干净地调用具有显式附加范围的子例程引用

Perl尽可能干净地调用具有显式附加范围的子例程引用,第1张

概述我希望能够写出如下内容…… call_with_scope({ x => 47,}, sub { printf "$x\n"; printf "$y\n";}); 其中$y绑定在包含表达式的环境中(词法或动态,具体取决于符号). 我找到了一种方法,但它不需要在包含call_with_scope(…)的表达式中生效严格的“变量”,并且call_with_scope的实现在 我希望能够写出如下内容……

call_with_scope({    x => 47,},sub {    printf "$x\n";    printf "$y\n";});

其中$y绑定在包含表达式的环境中(词法或动态,具体取决于符号).

我找到了一种方法,但它不需要在包含call_with_scope(…)的表达式中生效严格的“变量”,并且call_with_scope的实现在将控制转移到回调之前使用eval创建本地绑定.

有没有办法避免在调用站点要求没有严格的“变量”,或者在不诉诸eval的情况下引用和更改局部变量的值?

为了完整起见,下面的代码片段实现了call_with_scope并打印47然后打印48.

#!/usr/bin/env perluse strict;use warnings;sub call_with_scope {    my ($env,$func) = @_;    my %property;    my @preamble;    foreach my $k (keys %$env) {        $property{$k} = $env->{$k};        # deliberately omitted: logic to ensure that ${$k} is a well-formed variable        push @preamble,"local $$k = $property{'$k'};";    }    # force scalar context    do {        my $str = join('','no strict "vars";',@preamble,'$_[1]->();');        return scalar(eval($str));    };}                        do {    no strict 'vars';    local $x;    my $y = 48;    call_with_scope(        {            x => 47,sub {            printf "$x\n";            printf "$y\n";        }    );};
解决方法

I’m trying to write something kind of like Test::LectroTest … except that instead of using a source filter and comments like in Property { ##[ x <- Int,y <- Int ]## <body> } … I want to write something like Property({x => gen_int,y => gen_int},sub { <body> }) where $x and $y insIDe body get their values when an “instantiation” of a property test is performed.

您可以通过在调用者的包中将$x和$y定义为全局变量来实现此目的.

no strict 'refs';my $caller = caller;for my $var (keys %$propertIEs) {    *{$caller.'::'.$var} = $propertIEs->{$var};}$code->();

但这不容易本地化.使用全局变量污染调用者的命名空间可能会导致测试之间出现神秘的数据泄露.通常,在测试库中使用尽可能少的魔法;用户将有足够的自己奇怪的魔法来调试.

相反,提供一个返回属性的函数.例如,p.

package LectroTest;use Exporter qw(import);our @EXPORT = qw(test p);our $P;sub test {    my($props,$test) = @_;    local $P = $props;    $test->();}sub p {    return $P;}

测试看起来像:

use LectroTest;test(    { x => 42 },sub { print p->{x} });
总结

以上是内存溢出为你收集整理的Perl尽可能干净地调用具有显式附加范围的子例程引用全部内容,希望文章能够帮你解决Perl尽可能干净地调用具有显式附加范围的子例程引用所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1213499.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存