Perl变量初始化错误在子例程中使用

Perl变量初始化错误在子例程中使用,perl,subroutine,Perl,Subroutine,所以我有一个情况,我有一个有两个命名参数的函数,但是如果两者都被使用,这个函数就需要终止。我不确定这是否是一个bug,或者是否有一些我不了解的关于Perl变量的内在内容 以下是简化代码: #!/usr/bin/perl use strict; use warnings; use Data::Dumper; foreach my $number (1..5) { fooBar(foo => $number); } sub fooBar { my %args = (

所以我有一个情况,我有一个有两个命名参数的函数,但是如果两者都被使用,这个函数就需要终止。我不确定这是否是一个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
不应该在它失败后初始化
(如果定义了
测试),要么c)
@bar
应该抱怨它正在通过循环第二次重新初始化。我很困惑,这只是一个bug吗?

这只会有条件地创建一个新变量,并可能导致奇怪的结果:

my $foo = $args{foo} if defined $args{foo};
有这样的说法:

注意:my、state或our modified with语句修饰符条件或循环构造(例如my$x if…)的行为未定义。my变量的值可能是未定义的、任何先前指定的值,或者可能是任何其他值。不要依赖它。未来版本的perl可能会做一些与您试用的perl版本不同的事情。这里有龙


不要试图定义
$foo
变量;只需使用
$args{foo}
。或者无条件地完成任务;分配undef没有什么错。

啊,你想在Perl中找到bug吗?您真的理解Perl在代码中所理解的内容吗?;)我认为lazyif子句中的赋值(do{my$var=value;}if-value);应该会引起问题不要做我的。。。如果
。但实际发生的情况(目前,文档中将其标记为可能发生更改)是
my
具有编译时和运行时两种效果;if可以跳过运行时效果,使perl不知道它需要在作用域末尾重新初始化变量。在这种情况下,也可以尝试
perlcritic
:它说:在第22行第5列的条件语句中声明的变量。在条件之外声明变量。(严重程度:5)(第23行也是如此)非常有趣。我用这种方式格式化代码还有其他原因,但在我的示例中并不明显,尽管仔细看一下,我。。。不知道这些原因是什么。也许我会把它扔掉,看看有什么坏掉了。感谢您的回复:)@JasonHamje,文档。。。你知道你应该做什么;)@我想他是在向Jason说明为什么编写自己的代码很好。因为Jason说他格式化代码还有其他原因,但他记不起来了。如果他把它们记录下来,他就不必记得了。@gaussblurinc;够公平,够公平:P@ysth嗯,英国的讽刺很简单。。呃,不,我是说OP以后应该读它