perl - 你如何在没有 eval 的情况下本地化一些遗留的全局变量?

标签 perl global-variables scope

我问这个问题是因为我终于解决了一个问题,我一直试图在许多情况下找到一种技术。我认为它非常简洁,所以我正在对此进行问答。

看,如果我可以使用 eval ,我会这样做:

eval join( "\n"
         , map { 
             my $v = $valcashe{$_}; 
             sprintf( '$Text::Wrap::%s = %s', $_
                    , ( looks_like_number( $v ) ? $v : "'$v'" )
                    )
          }
        );
Text::Wrap::wrap( '', '', $text );

我什至试图变得棘手,但似乎 local将符号本地化到虚拟块,而不是物理块。所以这不起作用:
ATTR_NAME: while ( @attr_names ) {
    no strict 'refs';
    my $attr_name       = shift;
    my $attr_name       = shift @attr_names;
    my $attr_value      = $wrapped_attributes{$attr_name};
    my $symb_path       = "Text\::Wrap\::$attr_name";
    local ${$symb_path} = $attr_value;
    next ATTR_NAME if @attr_names;

    Text::Wrap::wrap( '', '', $text );

}

相同的物理块,我在设置前后测试了包变量,它们甚至在循环中显示了正确的时间值。但测试表明,只有最后一个变量通过的变量保留了它对 wrap 的调用的值。 .所以值只保持本地化直到循环结束。

我认为解决方案很简洁——即使是神秘的 perl 魔法。但最终结果是好的,因为这意味着我可以包装依赖于包范围变量的遗留代码,并确保设置的值尽可能短。

最佳答案

斧王,你这个白痴!包 stash 也是一个哈希值!这有效:

local @Text::Wrap::{ keys %wrapped_attributes } 
    = \( values %wrapped_attributes )
    ;

这将执行以下操作:
  • 它访问 Text::Wrap 的数组切片的符号表并返回命名的符号。
  • 因为它是一个符号而不是标量,为了让 perl 知道正确的插槽,你必须分配引用。对于数组和散列也是如此,但我们都知道它们的引用更常见。
  • \( ... )语法为列表中的每个项目传回一个引用。

  • 所以我们本地化 %wrapped_attributes 中每个键的每个变量,我们为它的每个值分配一个引用。

    它既丑陋又神秘,每次我需要它时都很难将它移开——但是有了它,我可以预先指定并延迟定位以选择我可以放置 Damien Conway 建议的带刺铁丝网和危险的地方迹象。

    如果我要使用它,它必须在我使用它的地方丑陋。

    关于perl - 你如何在没有 eval 的情况下本地化一些遗留的全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1540539/

    相关文章:

    perl - 使用 while(<>) ARGV[1] 格式的 perl 命令行参数,可能使用 shift 命令?

    Perl 运算符含义::和->

    ruby-on-rails - Rails Scope返回all而不是nil

    perl - 使用 Perl 从文件中获取数据

    perl - 无法获得政策Perl::Critic::Policy::Tics::ProhibitLongLines可以正常工作

    Python:如何使用 pprocess 修改函数中的全局变量

    python-3.x - 替代全局变量?

    objective-c - 从函数外部的 C 风格函数访问 NSString

    ruby - 对于 ruby​​ 中的深度命名空间,如何最好地管理编码风格和作用域运算符的烦恼?

    scope - 在以 playbook 为目标的 ansible 主机中使用变量