16 Stimmen

Wann ist es OK, eine undefinierte Variable in Perl mit aktivierten Warnungen zu verwenden?

Wenn Warnungen aktiviert sind, gibt Perl normalerweise Use of uninitialized value $foo もし $foo in einem Ausdruck verwendet wird und kein Wert zugewiesen wurde, aber in manchen Fällen ist das in Ordnung, und die Variable wird als falsch , 0 , oder '' ohne Vorwarnung.

In welchen Fällen kann eine nicht initialisierte/undefinierte Variable ohne Warnung verwendet werden?

19voto

Greg Bacon Punkte 127209

Resumen

  • Boolesche Tests
  • Inkrementieren oder Dekrementieren eines undefinierten Wertes
  • Anhängen an einen undefinierten Wert
  • Autovivifizierung
  • Andere Mutatoren

Boolesche Tests

Nach Angaben der perlsyn-Dokumentation ,

Die Zahl 0 die Saiten '0' y '' die leere Liste () y undef sind in einem booleschen Kontext alle falsch. Alle anderen Werte sind wahr.

Da der undefinierte Wert falsch ist, wird das folgende Programm

#! /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";

Ausgänge D über G ohne Warnungen.

Inkrementieren oder Dekrementieren eines undefinierten Wertes

Es besteht keine Notwendigkeit, einen Skalar explizit auf Null zu initialisieren, wenn Ihr Code ihn mindestens einmal inkrementieren oder dekrementieren wird:

#! /usr/bin/perl

use warnings;

my $i;
++$i while "aaba" =~ /a/g;
print $i, "\n";

Der obige Code gibt Folgendes aus 3 ohne Warnungen.

Anhängen an einen undefinierten Wert

Ähnlich wie bei der impliziten Null ist es nicht nötig, Skalare explizit mit der leeren Zeichenkette zu initialisieren, wenn man mindestens einmal an sie anhängt:

#! /usr/bin/perl

use warnings;
use strict;

my $str;
for (<*>) {
  $str .= substr $_, 0, 1;
}
print $str, "\n";

Autovivifizierung

Ein Beispiel ist die "Autovivifizierung". Aus dem Wikipedia-Artikel :

Autovivification ist ein besonderes Merkmal der Programmiersprache Perl, das die dynamische Erstellung von Datenstrukturen ermöglicht. Autovivification ist die automatische Erzeugung einer Variablenreferenz, wenn ein undefinierter Wert dereferenziert wird. Mit anderen Worten: Perl-Autovivifikation erlaubt es einem Programmierer, auf eine strukturierte Variable und beliebige Unterelemente dieser strukturierten Variable zu verweisen, ohne die Existenz der Variable und ihre vollständige Struktur vorher ausdrücklich zu deklarieren.

Zum Beispiel:

#! /usr/bin/perl

use warnings;

my %foo;
++$foo{bar}{baz}{quux};

use Data::Dumper;
$Data::Dumper::Indent = 1;
print Dumper \%foo;

Auch wenn wir die Zwischenschlüssel nicht explizit initialisieren, kümmert sich Perl um das Gerüst:

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

Ohne die automatische Belebung würde der Code mehr Textbausteine erfordern:

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

Verwechseln Sie die Autovivifizierung nicht mit den undefinierten Werten, die sie hervorbringen kann. Zum Beispiel mit

#! /usr/bin/perl

use warnings;

my %foo;
print $foo{bar}{baz}{quux}, "\n";
use Data::Dumper;
$Data::Dumper::Indent = 1;
print Dumper \%foo;

erhalten wir

Use of uninitialized value in print at ./prog.pl line 6.

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

Beachten Sie, dass die Zwischenschlüssel autovivifiziert sind.

Andere Beispiele für Autovivifikation:

  • Verweis auf Array

    my $a;
    push @$a => "foo";
  • Referenz auf Skalar

    my $s;
    ++$$s;
  • Verweis auf Hash

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

Leider kann Perl das Folgende (noch!) nicht autovivifizieren:

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

Andere Mutatoren

In einer Antwort auf eine ähnliche Frage , berichtet ysth

Bestimmte Operatoren lassen die Warnung "uninitialized" absichtlich weg, weil sie häufig in Situationen verwendet werden, in denen eine 0 oder "" als Standardwert für den linken oder einzigen Operanden sinnvoll ist.

Diese sind: ++ y -- (entweder vorher oder nachher), += , -= , .= , |= , ^= , &&= , ||= .

"Definiert-oder" sein //= mutiert fröhlich einen undefinierten Wert ohne Warnung.

2voto

Frank Szczerba Punkte 4900

Bislang habe ich folgende Fälle gefunden:

  • Autovivifizierung ( Antwort von gbacon )
  • boolescher Kontext, wie if $foo o $foo || $bar
  • con ++ o --
  • linke Seite von += , -= , oder .=

Gibt es noch andere?

2voto

Evan Carroll Punkte 1

Immer Warnungen korrigieren sogar die lästigen Nervensägen.

Undefinierte Warnungen können ausgeschaltet werden. Sie können dies tun, indem Sie einen neuen Bereich für die Operation erstellen. Siehe perldoc perllexwarn für weitere Informationen. Diese Methode funktioniert in allen Versionen von Perl.

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

Für viele der binären Operatoren können Sie die neuen Perl 5.10-Funktionen verwenden, ~~ y // ; Siehe perldoc perlop für weitere Informationen.

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

ist auch die //= Variante, die die Variable setzt, wenn sie undefiniert ist:

$foo //= '';

Das Smart Matching ( ~~ ) Operator ist ziemlich cool und erlaubt intelligente Vergleiche, das ist ganz schön raffiniert. perldoc perlsyn :

use warnings;
my $foo = "string";
say $foo eq undef;  # triggers warnings
say $foo ~~ undef;  # no undef warnings

0voto

Sam Kington Punkte 1202

Die eigentliche Antwort sollte lauten: Warum sollten Sie diese Warnung einschalten? undef ist ein sehr guter Wert für eine Variable (wie Ihnen jeder bestätigen kann, der schon einmal mit einer Datenbank gearbeitet hat), und es ist oft sinnvoll, zwischen true (etwas ist passiert), false (nichts ist passiert) und undef (ein Fehler ist aufgetreten) zu unterscheiden.

Anstatt zu sagen

use strict;
use warnings;

sagen

use common::sense;

und Sie erhalten alle Vorteile von Warnungen, aber mit den lästigen wie undefinierte Variablen ausgeschaltet.

common::sense ist im CPAN verfügbar.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X