Perl 不会删除标量变量。如何使其不将已删除变量的内容初始化为零?



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

我认为,在使用临时变量进行重要计算(例如管理预算)后,能够从脚本中完全删除临时变量的内容非常重要。但 Perl 似乎不同意。有没有办法使删除的变量不初始化为零?

下面是一个 Perl 5 脚本来检验这个假设:

#!/usr/bin/env perl
# deletion_attempt.pl
use warnings; 
print "Give me a positive number greater than zeron";
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内存中完全删除变量内容,而不会无意中将其初始化为零?

谢谢。

首先,始终使用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_logn";
}
{
#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_logn";
}

尝试运行上述内容失败,并显示以下编译时错误:

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不再在范围内。

Perl 告诉你这个问题。您会收到警告:

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

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

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

use warnings FATAL => 'uninitialized';

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

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

最新更新