所以我有一种情况,我有一个带有两个命名参数的函数,但是如果两者都被使用,那么函数需要死掉。我不确定这是不是一个bug,或者是否存在内在的东西,我不了解Perl变量。
以下是简化代码:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
foreach my $number (1..5)
{
fooBar(foo => $number);
}
sub fooBar
{
my %args = (
foo => undef,
bar => undef,
@_
);
my $foo = $args{foo} if defined $args{foo};
my @bar = @{$args{bar}} if defined $args{bar};
print Dumper(\@bar);
if (defined $foo)
{
die('fooBar() received both a foo and a bar and didn\'t know which to use!') if @bar;
push(@bar, $foo);
}
print Dumper(\@bar);
return (\@bar);
}
# > $VAR1 = [];
# > $VAR1 = [
# > 1
# > ];
# > $VAR1 = [
# > 1
# > ];
# > fooBar() received both a foo and a bar and didn't know which to use! at ./example.pl line 27.
这是我的解决方案:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
foreach my $number (1..5)
{
fooBar(foo => $number);
}
sub fooBar
{
my %args = (
foo => undef,
bar => undef,
@_
);
my $foo;
my @bar;
$foo = $args{foo} if defined $args{foo};
@bar = @{$args{bar}} if defined $args{bar};
print Dumper(\@bar);
if (defined $foo)
{
die('fooBar() received both a foo and a bar and didn\'t know which to use!') if @bar;
push(@bar, $foo);
}
print Dumper(\@bar);
return (\@bar);
}
# > $VAR1 = [];
# > $VAR1 = [
# > 1
# > ];
# > $VAR1 = [];
# > $VAR1 = [
# > 2
# > ];
# > $VAR1 = [];
# > $VAR1 = [
# > 3
# > ];
# > $VAR1 = [];
# > $VAR1 = [
# > 4
# > ];
# > $VAR1 = [];
# > $VAR1 = [
# > 5
# > ];
我的问题是,为什么这可以解决问题?在第一个示例中,第一次调用fooBar()
时,@bar
正在初始化,尽管if条件失败。第二次通过循环,@bar
以某种方式保留了第一个循环的信息,但它没有抱怨重新初始化。在我看来,a)@bar
应该在子程序结束后擦除(这是我所期待的),b)@bar
在if defined
失败后不应该被初始化测试,或c)@bar
应该抱怨它在循环中第二次重新初始化。我在这里很困惑,这只是一个错误吗?
答案 0 :(得分:7)
这只会有条件地创建一个新变量,并且可能导致奇怪的理解结果:
my $foo = $args{foo} if defined $args{foo};
perldoc perlsyn有这样的说法:
注意:my,state或我们使用语句修饰符条件或循环结构修改的行为(例如,我的$ x if ...)是未定义的。 my变量的值可以是undef,任何先前分配的值,或者可能是其他任何值。不要依赖它。 perl的未来版本可能会与您尝试使用的perl版本有所不同。这里是龙。
不要试图定义$foo
变量;只需使用$args{foo}
。或者只是无条件地完成任务;分配undef没什么问题。