我的脚本中有以下几行:
my $spec = shift;
if (!defined $spec) {
return ("Invalid specification", undef);
}
$spec = "$spec" // '';
Run Code Online (Sandbox Code Playgroud)
我自然希望这会在传递undef时返回Invalid specification数组中的警告,第二项是undef.相反,检查通过,我得到一个控制台消息警告我Use of uninitialized value $spec in string下一行.
$spec是一个带有字符串和数字重载的对象,不幸的是这样写入,试图在这个特定子程序中测试真实性(if ($spec)例如),导致深度递归和段错误.
虽然我很感兴趣,为什么,到底,发生这种情况,我更感兴趣的是如何使它停止发生.我想消除控制台警告,最好没有no warnings qw/uninitialized/.这是可能的,如果是的话,我该怎么做?
你说那$spec是一个带字符串重载的对象.
如果是这种情况,那么在检查它是否被定义之前,您需要将其强制转换为String形式:
if (! defined overload::StrVal($spec)) {
Run Code Online (Sandbox Code Playgroud)
每月更正
正如在StrVal中指出的那样,没有强制重载的字符串化:
过载:: StrVal(ARG)
在没有stringify重载的情况下给出arg的字符串值.如果你使用它来获取引用的地址(用于检查两个引用是否指向同一个东西)那么你最好使用Scalar :: Util :: refaddr(),这样会更快.
因此,要实现这一点,请尝试他的另一个建议:
"$ spec"捕获警告并检测未初始化的var警告.最好在类中添加一个方法来测试返回undef的任何情况.
以下演示了这种方法:
#!/usr/bin/env perl
use strict;
use warnings;
use Test::More tests => 2;
my $obj_str_defined = StringOverloaded->new("has value");
my $obj_str_undef = StringOverloaded->new(undef);
ok( is_overloaded_string_defined($obj_str_defined), qq{\$obj_str_defined is defined} );
ok( !is_overloaded_string_defined($obj_str_undef), qq{\$obj_str_undef is undef} );
sub is_overloaded_string_defined {
my $obj = shift;
my $is_str_defined = 1;
local $SIG{__WARN__} = sub {
$is_str_defined = 0 if $_[0] =~ /Use of uninitialized value \$obj in string/;
};
my $throwaway_var = "$obj";
return $is_str_defined;
}
{
# Object with string overloading
package StringOverloaded;
use strict;
use warnings;
use overload (
'""' => sub {
my $self = shift;
return $$self; # Dereference
},
fallback => 1
);
sub new {
my $pkg = shift;
my $val = shift;
my $self = bless \$val, $pkg;
return $self;
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
1..2
ok 1 - $obj_str_defined is defined
ok 2 - $obj_str_undef is undef
Run Code Online (Sandbox Code Playgroud)