如何通过返回子功能来避免变量被触及。我写了以下代码片段
#!/usr/bin/perl
use strict;
use warnings;
my $a = "init";
sub funct{
my $var;
#$var = 1;
return $var if defined $var;
}
my $tmp = funct;
$a = $tmp if defined $tmp;
print "$a\n";
如果子函数中未定义$a
,我不希望init
的值从其初始$var
更改。
错误在哪里或有更好的方法来解决这个问题?
问候
答案 0 :(得分:3)
您可以避免临时变量,
$a = funct() // $a;
答案 1 :(得分:3)
return $foo if $bar
相当于$bar and return $foo
。因此,当$bar
为false时,此语句将计算为$bar
的值。当子例程返回最后执行的语句的值时,如果定义了子语句,则子语句返回$var
,如果没有,则返回false值。
您可以选择显式路线,然后再返回:
# all branches covered
return $var if defined $var;
return;
这很愚蠢,相当于return $var
。
现在您的子返回的假值实际上已定义,因此它被分配给$a
。你可以测试一下真相:
$a = $tmp if $tmp;
......但这会打开另一种蠕虫病毒。
返回值非常不好告诉我们它们是否是所需的返回值或错误指示符。有两种方法:
返回第二个值,告诉我们函数是否退出OK:
sub func {
my $var;
return (1, $var) if defined $var;
return (0); # not strictly needed
}
my ($ok, $tmp) = func();
$a = $tmp if $ok;
(基本上,在Golang中看到的逗号成语)
返回必须解构的容器以获取实际返回值。可能是在出现错误时返回undef
(或错误),或者在存在这样的值时对值进行标量引用:
sub func {
my $var;
return \$var if defined $var;
return undef; # actually not needed
}
my $tmp = func();
$a = $$tmp if defined $tmp;
(基本上,在Haskell中看到的Maybe
类型)
这是一种在没有冷静的临时变量的情况下使用它的方法:
($a) = map { $_ ? $$_ : () } func(), \$a;
答案 2 :(得分:1)
在Perl调试器中运行此程序显示$tmp
设置为空字符串,使用defined
函数计算结果为true。这就是设置$a
的条件求值为true的原因:
$ perl -d
Loading DB routines from perl5db.pl version 1.33
Editor support available.
Enter h or `h h' for help, or `perldoc perldebug' for more help.
use strict;
use warnings;
my $a = "init";
sub funct{
my $var;
#$var = 1;
return $var if defined $var;
}
my $tmp = funct;
$a = $tmp if defined $tmp;
print "$a\n";
__END__
main::(-:4): my $a = "init";
DB<1> x $a
0 undef
DB<2> n
main::(-:12): my $tmp = funct;
DB<2> x $a
0 'init'
DB<3> x $tmp
0 undef
DB<4> n
main::(-:14): $a = $tmp if defined $tmp;
DB<4> x $tmp
0 ''
仅使用return $var
修复if defined $var
。这会将$tmp
设置为undef
答案 3 :(得分:0)
看起来您正在尝试通过返回undef
来检测错误情况。除了@ amon的建议,当发生错误时,die
可以funct
:
#!/usr/bin/perl
use strict;
use warnings;
my $a = "init";
sub funct{
my $var;
...
if ($something_went_wrong) {
die 'something bad';
}
...
return $var;
}
eval {
$a = funct;
1;
} or do {
# log/handle the error in $@
};
print "$a\n";