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

时间:2014-08-15 17:58:56

标签: 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 = (
        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)@barif defined失败后不应该被初始化测试,或c)@bar应该抱怨它在循环中第二次重新初始化。我在这里很困惑,这只是一个错误吗?

1 个答案:

答案 0 :(得分:7)

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

my $foo = $args{foo} if defined $args{foo};

perldoc perlsyn有这样的说法:

  

注意:my,state或我们使用语句修饰符条件或循环结构修改的行为(例如,我的$ x if ...)是未定义的。 my变量的值可以是undef,任何先前分配的值,或者可能是其他任何值。不要依赖它。 perl的未来版本可能会与您尝试使用的perl版本有所不同。这里是龙。

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