我有一个更新RSS源的Perl子例程。我想测试返回的值,但是函数在很多地方使用,所以我只想测试默认变量$_
,据我所知,如果没有指定变量,应该为其分配返回值。
代码有点太长而无法包含所有内容,但实质上它会执行以下操作
sub updateFeed {
#....
if($error) {
return 0;
}
return 1;
}
为什么会这样做
$rtn = updateFeed("My message");
if ($rtn < 1) { &Log("updateFeed Failed with error $rtn"); }
不记录任何错误
,而
updateFeed("myMessage");
if ($_ < 1) { &Log("updateFeed Failed with error $_"); }
记录错误“updateFeed Failed with error
”? (注意消息末尾没有值。)
有谁能告诉我为什么默认变量似乎包含空字符串或undef?
答案 0 :(得分:9)
因为Perl不能那样工作。 $_
不会自动获取void上下文中调用的函数的结果。默认情况下,有一些内置运算符可以读写$_
和@_
,但是如果你编写代码来实现它,你自己的子程序就会这样做。
答案 1 :(得分:7)
普通函数调用不是隐式使用$_
的上下文之一。
以下是perldoc perlvar
(截至v5.14.1)对$_
所说的内容:
$ _
默认输入和模式搜索空间。以下对是等价的:
while (<>) {...} # equivalent only in while!
while (defined($_ = <>)) {...}
/^Subject:/
$_ =~ /^Subject:/
tr/a-z/A-Z/
$_ =~ tr/a-z/A-Z/
chomp
chomp($_)
以下是Perl假设$ _的地方,即使你不使用它:
以下函数使用$ _作为默认参数:
abs,闹钟,chomp,印章,chr,chroot,cos,定义,eval,exp,glob,hex,int,lc,lcfirst,长度,日志,lstat,mkdir,oct,ord,pos,打印,quotemeta ,readlink,readpipe,ref,require, 反向(仅在标量上下文中),rmdir,sin,split(在其第二个参数上),sqrt,stat,study,uc,ucfirst,unlink,unpack。
所有文件测试(
-f
,-d
)除了-t
,默认为STDIN。请参阅perlfunc中的-X
在没有
m//
运算符的情况下使用模式匹配操作s///
,tr///
和y///
(又名=~
)。如果没有提供其他变量,则
foreach
循环中的默认迭代器变量。
grep()
和map()
函数中的隐式迭代器变量。隐含变量
given()
。将
<FH>
操作的结果作为while
测试的唯一标准进行测试时,输入记录的默认位置。在while
测试之外,这不会发生。由于$ _是一个全局变量,这可能会在某些情况下导致不必要的副作用。从perl 5.9.1开始,您现在可以通过在
my
的文件或块中声明它来使用$ _的词法版本。 此外,声明our $_
恢复当前范围内的全局$ _。助记符:在某些操作中理解下划线。
答案 2 :(得分:5)
你从未将标志分配给$_
,为什么它会包含你的旗帜?它似乎包含一个空字符串(或者可能是undef
,它带有一个警告字符串化为空字符串。)
答案 3 :(得分:0)
$_
不是由void上下文中的子例程设置的。当void为context时,可以编写你的子集以设置$_
。首先检查wantarray
的值,并在$_
未定义时设置wantarray
。
sub updateFeed {
...
my $return
...
if($error) {
$return = 0;
}else{
$return = 1;
}
# $return = !$error || 0;
if( defined wantarray ){ # scalar or list context
return $return;
}else{ # void context
$_ = $return;
}
}
我建议不要这样做,因为对于正在使用你的子程序的人来说这可能是一个惊喜。这可能会使调试程序变得更加困难。
关于我唯一一次这样做,就是模仿built-in subroutine。