【问题标题】:Is there a built-in function to clear all variable values是否有清除所有变量值的内置函数
【发布时间】:2011-08-27 12:47:32
【问题描述】:

我正在寻找一种方法来清除 Perl 程序中的所有数组。

目前,我正在调用一个显式“重置”所有数组的子程序:

sub clear_arrays{(@array1,@array2,@array3)=((),(),());}

这迫使我找到程序中的所有数组并在子例程中逐字引用它们。

我查看了 resetundefdelete 的 perldoc,但无法以清除所有数组的方式解释它们。

是否有 Perl 的内置函数可以做到这一点?

如果没有,是否有一个函数会返回一个包含所有数组变量的数组?

例如:

my @prog_arrays = getarrays();
foreach(@prog_arrays){$_ = ();}

getarrays() 可能是一个内置的 Perl 函数,它返回程序中任何/所有已初始化的数组。


编辑:
我的特殊情况只涉及两个需要重置的全局数组。我出于好奇而不是必要性扩大了这个问题。基本上,我的全局变量是@email_subject@email_msg

随着脚本的进展和数据的收集/分析,它们的值被推送到其中。在脚本结束时,将发送电子邮件消息,并且脚本可能会根据循环条件变量再次运行。

如果它再次运行,我需要清除这 2 个全局变量,以便它们可以在下一个循环周期中再次聚合。通过字面量引用清除这两个数组并没有害我死,但我只是想知道 Perl 是否已经有一些内置函数可以在不直接引用它们的情况下清除数组。

这可能不是实现此目的的最佳方式,但这是我考虑的第一个直观选项。

【问题讨论】:

  • 不是一个答案,只是一个建议(它适用于我处理的每种语言):只需根据需要管理每个对象的范围和生命周期。对象的聚合/组合(“OO”或其他)和全局变量的消除/减少简化了设计。
  • 三个赞成票让我担心。有些人想要这样做。切勿在未锁车门的情况下开车
  • 这个问题寻求一种方法来规避 Perl 的内置保护以防止不良编程。可悲的是有人想帮忙

标签: arrays perl reset undef


【解决方案1】:

正如其他答案中提到的,您的请求说明了您的程序设计存在更大的问题。您应该使用超出范围的词法,或者密切管理所有全局数组,并创建一个函数来为您清除它们。

如果你坚持要对命名空间中的每个数组进行钝化,至少要小心并检查以确保你没有写入 Perl 可能需要的值:

for (keys %::) {  # for everything in `package main;`
    if (*{$::{$_}}{ARRAY}) {  # if there is an array in the slot
        # clear it unless it is a "special" array
        @{$::{$_}} = () unless /^(?:INC|ISA|EXPORT|EXPORT_OK|ARGV|_|\W)$/
    }
}

我会这样写:

my @global_arrays = \our (@foo, @bar, @baz);
sub clear_global_arrays {
    @$_ = () for @global_arrays
}

所讨论的数组的效果是相同的,但它不会冒破坏任何您不打算破坏的风险。您甚至可以在第二个示例中使用my 而不是our,而第一个示例要求变量位于符号表中(也就是使用our 定义)。

【讨论】:

  • 我真希望你没有公开描述如何杀死你的祖母并获得她的遗产
【解决方案2】:

你想要这个的事实对我来说是“糟糕的设计”。但是,假设您确切地知道您在用这个放射性电锯做什么,您可以通过访问全局符号表哈希%::%main:: 来完成它。 (冒号是名称的一部分。)此哈希包含从每个已定义的全局符号到对其变量的引用的映射。

这样就足够了:

for my $ref (values %::) {
    @{$ref} = ();
}

已编辑以删除对数组引用的检查。所有值实际上都是 typeglob 引用,因此无需检查。

【讨论】:

  • 哎呀!危险威尔罗宾逊! *arms flailing*
  • 不确定ref 的用途。当我尝试它时(在 5.10.1 和 5.14.0 上),它不会清除全局变量。这将:perl -Mstrict -wE 'for (values %::) { say; @{$_} = () } say for @INC;' 正如你所说,你不想在生产中使用它。 :-) 另外,这提醒了我曾经在 Java 中是如何使用 Properties props = new Properties(); props.setProperty(name, value); System.setProperties(props); 的。 :-)
  • 我刚刚将显示名称更改为 Lumi。很想知道 SO 是否会通过 cmets 中对我名字的所有引用来传播该更改。它不会。 :-)
  • 您示例中的for 循环将一个空数组安装到%:: 中的每个现有条目中,而不仅仅是那些已经包含数组的条目。你想要像for (keys %::) {@{$::{$_}} = () if *{$::{$_}}{ARRAY}} 这样的东西,它只会清除现有的数组而不会创建新的数组。理想情况下,您还应该对 glob 名称运行正则表达式,以确保您没有清除 @_@INC@ISA 之类的内容。
【解决方案3】:

不要使用全局数组。就这么简单。词法数组仅限于声明它们的作用域,当你进入作用域时会自动开始为空。

如果您必须使用全局变量,无论如何在一个地方跟踪它们都是一个好主意,因此清除它们应该不难。

曾经有人发布了一个现在臭名昭著的工具来让 perlmonks 做你想做的事。在收到对整个想法的大量批评后,该代码被撤回;你可以在这里阅读一些批评:http://www.perlmonks.org/index.pl?node_id=349496

【讨论】:

  • OP 正在寻求一种方法来规避 Perl 对不良编程的内置保护。可悲的是,有人想帮忙。谢谢你不是他们中的一员
猜你喜欢
  • 1970-01-01
  • 2015-05-15
  • 1970-01-01
  • 2014-06-22
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2021-04-30
  • 2023-03-19
相关资源
最近更新 更多