我问这个问题是因为我终于解决了一个问题,我一直试图在很多情况下找到一种技术。我觉得它非常整洁所以我正在做这个Q-and-A。
请参阅,如果我可以使用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 );
}
相同的物理块,我在设置之前和之后测试了包变量,他们甚至在他们的时间通过循环显示了正确的值。但是测试显示只有传递的 last 变量保留了它对wrap
的调用的值。所以值只保持本地化直到循环结束。
我认为解决方案很简洁 - 即使是神秘的perl magick。但最终结果是好的,因为这意味着我可以包装依赖于包范围变量的遗留代码,并确保设置的值尽可能短。
答案 0 :(得分:6)
local @Text::Wrap::{ keys %wrapped_attributes }
= \( values %wrapped_attributes )
;
执行以下操作:
Text::Wrap
符号表的数组切片并返回命名符号。\( ... )
语法传回列表中每个项目的引用。 因此,我们为%wrapped_attributes
中的每个键本地化每个变量,并为其分配每个值的引用。
这很丑陋,而且每次我需要时都很难将它移开 - 但有了它,我可以预先指定并延迟本地化以选择我所在的地方可以提出Damien Conway建议的铁丝网和危险标志。
如果我要使用它,它必须只是我使用它的丑陋。