Perl没有删除标量变量。如何才能将已删除变量的内容初始化为零?

时间:2017-06-18 00:59:02

标签: perl

我有一个简单的脚本来接受标准输入。我请求变量是一个数字。但显然标准输入可能需要像“Hello World”这样的字符串。我尝试通过使用“undef”使其未定义来删除变量,但是未定义的函数使我的变量为零。然后我做一些数学运算,看看未定义的函数是否实际上使我的标量值为零,或者是否从内存中删除变量,因为零的自然对数是未定义的。

我认为能够在完成重要计算之后从脚本中完全删除临时变量的内容非常重要,例如管理预算。但Perl似乎不同意。反正有没有将被删除的变量初始化为零?

这是一个测试该假设的Perl 5脚本:

#!/usr/bin/env perl
# deletion_attempt.pl
use warnings; 

print "Give me a positive number greater than zero\n";
chomp($x = <STDIN>);

$this_log = log($x);
print "The natural logarithm of $x is $this_log";

undef $x; # I'm trying to delete $x. But Perl is initializing $x to zero. 

$new_log = log($x);
print "The natural logarithm of the deleted variable is $new_log";

print "$x";

如果我从标准输入中提供10,我会将此结果提供给标准输出。

Give me a positive number greater than zero
10
Use of uninitialized value $x in log at deletion_attempt.pl line 13, <STDIN> line 1.
Can't take log of 0 at deletion_attempt.pl line 13, <STDIN> line 1.
The natural logarithm of 10 is 2.30258509299405

如果我注释掉我计算未定义标量值$ x的自然对数的行,我被告知该值未定义,但不是它为零。

Give me a positive number greater than zero
10
Use of uninitialized value $x in string at deletion_attempt.pl line 16, <STDIN> line 1.
The natural logarithm of 10 is 2.30258509299405

所以Perl并没有告诉我实情。它正在通过使其未定义而将我想要删除的变量赋值为零。它正在进行赋值,而不是从Perl内存中删除变量或其内容。

另一种像R这样的语言足够聪明,可以删除x的变量,而不是将其设置为零,这样你就可以对它进行数学运算。所以这个实现让我对Perl编程不太乐观。

> x = 10
> log(x)
[1] 2.302585
> rm(x)
> x
Error: object 'x' not found
> log(x)
Error: object 'x' not found

所以我的问题是:有没有办法从Perl内存中完全删除变量内容而不会无意中将其初始化为零?

谢谢。

2 个答案:

答案 0 :(得分:4)

首先,始终使用use strict; use warnings qw( all );。这避免了这么多问题,它专门解决了你的问题,因为除其他外,这将阻止你隐式创建全局变量。您必须使用my声明变量,并且声明它们将影响它们的显示和使用位置。

例如,参加以下计划:

#!/usr/bin/env perl
use strict;
use warnings qw( all ); 

{    
   print "Give me a positive number greater than zero: ";
   chomp(my $x = <STDIN>);

   my $this_log = log($x);
   print "The natural logarithm of $x is $this_log\n";
}

{
   #print "Give me a positive number greater than zero: ";
   #chomp(my $x = <STDIN>);

   my $new_log = log($x);
   print "The natural logarithm of $x is $new_log\n";
}

尝试运行上述操作失败时出现以下编译时错误:

Global symbol "$x" requires explicit package name (did you forget to declare "my $x"?) at a.pl line 17.
Global symbol "$x" requires explicit package name (did you forget to declare "my $x"?) at a.pl line 18.
Execution of a.pl aborted due to compilation errors.

该程序因为您尝试使用不存在的变量而死亡,证明$x已不在范围内。

答案 1 :(得分:3)

Perl告诉你这个问题。你得到警告:

  

在日志中使用未初始化的值$ x

但是警告只是警告。 Perl将继续并尝试做正确的事情。当谈到未初始化的值时,Perl将它们视为空字符串或数字零,具体取决于您使用它们的上下文。

如果您不希望Perl这样做,请将警告升级为致命错误:

use warnings FATAL => 'uninitialized';

然后,如果您尝试访问未初始化的值,您仍会看到相同的警告消息,但您的程序也将在此时死亡。

更新:我应该指出,虽然这解决了你当前的问题,但我同意100%与ikegami,它正在解决你真正不应该有的问题。正如你所描述的那样“删除变量”(实际上,只是将其值设置为“undef”)并不是最好的方法。您应该更仔细地考虑变量的范围。