代码之家  ›  专栏  ›  技术社区  ›  Frank Szczerba

什么时候可以在perl中使用未定义的变量并启用警告?

  •  14
  • Frank Szczerba  · 技术社区  · 16 年前

    Use of uninitialized value $foo 如果 $foo 在表达式中使用,但尚未指定值,但在某些情况下可以,并且变量被视为 假的 0 '' 没有警告。

    在什么情况下,未初始化/未定义的变量可以在没有警告的情况下使用?

    4 回复  |  直到 16 年前
        1
  •  19
  •   Community Mohan Dere    9 年前

    总结

    • 布尔测试
    • 递增或递减未定义的值
    • 附加到未定义的值
    • 自生
    • 其他突变子

    根据 perlsyn documentation ,

    号码 0 '0' 和 '' ,空列表 () undef 在布尔上下文中都为false。所有其他值均为真。

    #! /usr/bin/perl
    
    use warnings;
    
    my $var;
    print "A\n" if $var;
    $var && print "B\n";
    $var and print "C\n";
    print "D\n" if !$var;
    print "E\n" if not $var;
    $var or print "F\n";
    $var || print "G\n";
    

    输出 D 通过 G

    递增或递减未定义的值

    #! /usr/bin/perl
    
    use warnings;
    
    my $i;
    ++$i while "aaba" =~ /a/g;
    print $i, "\n";
    

    上面的代码输出 3 没有警告。

    附加到未定义的值

    与隐式零类似,如果将至少一次附加到空字符串,则无需显式将标量初始化为空字符串:

    #! /usr/bin/perl
    
    use warnings;
    use strict;
    
    my $str;
    for (<*>) {
      $str .= substr $_, 0, 1;
    }
    print $str, "\n";
    

    一个例子是“自生” Wikipedia article :

    例如:

    #! /usr/bin/perl
    
    use warnings;
    
    my %foo;
    ++$foo{bar}{baz}{quux};
    
    use Data::Dumper;
    $Data::Dumper::Indent = 1;
    print Dumper \%foo;
    

    即使我们没有显式初始化中间键,Perl也会处理脚手架:

    $VAR1 = {
      'bar' => {
        'baz' => {
          'quux' => '1'
        }
      }
    };

    如果没有自动激活,代码将需要更多的样板文件:

    my %foo;
    $foo{bar} = {};
    $foo{bar}{baz} = {};
    ++$foo{bar}{baz}{quux};  # finally!
    

    #! /usr/bin/perl
    
    use warnings;
    
    my %foo;
    print $foo{bar}{baz}{quux}, "\n";
    use Data::Dumper;
    $Data::Dumper::Indent = 1;
    print Dumper \%foo;
    

    我们得到

    Use of uninitialized value in print at ./prog.pl line 6.
    
    $VAR1 = {
      'bar' => {
        'baz' => {}
      }
    };

    • 对数组的引用

      my $a;
      push @$a => "foo";
      
    • 对标量的引用

      my $s;
      ++$$s;
      
    • my $h;
      $h->{foo} = "bar";
      

    遗憾的是,Perl(还没有!)自动激活以下内容:

    my $code;
    $code->("Do what I need please!");
    

    其他突变子

    In an answer to a similar question ,伊斯特报道

    这些是: ++ 和 -- (之前或之后-), += -= , .= , |= , ^= , &&= ||= .

    被定义或 //= 愉快地在没有警告的情况下变异未定义的值。

        2
  •  2
  •   Community Mohan Dere    9 年前

    • 自生( gbacon's answer )
    • if $foo 或 $foo || $bar
    • 具有 ++ 或 --
    • 左侧 += , -= .=

    还有其他的吗?

        3
  •  2
  •   Evan Carroll    16 年前

    即使 那些讨厌的。

    perldoc perllexwarn 更多信息。此方法适用于所有版本的perl。

    {
      no warnings 'uninitialized';
      my $foo = "foo" + undef = "bar";
    }
    

    对于许多二进制运算符,您可以使用新的Perl 5.10内容, ~~ // ; 看见 perldoc perlop 更多信息。

    use warnings;
    my $foo = undef;
    my $bar = $foo // ''; ## same as $bar = defined $foo ? $foo : ''
    

    也是 //=

    $foo //= '';
    

    智能匹配( ~~ perldoc perlsyn :

    use warnings;
    my $foo = "string";
    say $foo eq undef;  # triggers warnings
    say $foo ~~ undef;  # no undef warnings
    
        4
  •  0
  •   Sam Kington    16 年前

    真正的答案应该是:你为什么要打开这个警告?undef对于变量来说是一个非常好的值(任何使用过数据库的人都可以告诉您),区分true(发生了什么)、false(没有发生什么)和undef(发生了错误)通常是有意义的。

    use strict;
    use warnings;
    

    说

    use common::sense;
    

    common::sense可从CPAN获得。

    推荐文章