Frage

Da ich $ _ häufig verwende, möchte ich seine Verwendung besser verstehen. $ _ ist eine globale Variable für implizite Werte, soweit ich sie verstanden und verwendet habe.

Da $ _ ohnehin festgelegt zu sein scheint, gibt es neben Lesbarkeit Gründe, benannte Schleifenvariablen über $ _ zu verwenden?

In welchen Fällen spielt es eine Rolle, dass $ _ eine globale Variable ist?

Also wenn ich benutze

for (@array){
    print $_;
}

oder sogar

print $_ for @array;

hat den gleichen Effekt wie

for my $var (@array){
    print $var;
}

Aber funktioniert es genauso? Ich denke, es ist nicht genau, aber was sind die tatsächlichen Unterschiede?

Update :

In diesem Beispiel scheint $ _ sogar einen korrekten Gültigkeitsbereich zu haben. Ist es nicht mehr global? Ich verwende 5.12.3.

#!/usr/bin/perl
use strict;
use warnings;

my @array = qw/one two three four/;
my @other_array = qw/1 2 3 4/;

for (@array){
    for (@other_array){
        print $_;
    }
    print $_;
}

das korrekt druckt 1234one1234two1234three1234four.

Für globales $ _ hätte ich 1234 4 1234 4 1234 4 1234 4 .. oder erwartet Vermisse ich etwas Offensichtliches?

Wann ist dann $ _ global?

Update :

Ok, nachdem ich die verschiedenen Antworten und Perlsyn genauer gelesen hatte, kam ich zu dem Schluss:

Neben der Lesbarkeit ist es besser, die Verwendung von $ _ zu vermeiden, da die implizite Lokalisierung von $ _ bekannt sein und berücksichtigt werden muss, da sonst unerwartetes Verhalten auftreten kann.

Vielen Dank für die Klärung dieser Angelegenheit.

War es hilfreich?

Lösung

are there reasons to use named loop variables over $_ besides readability?

Das Problem ist nicht, ob sie benannt sind oder nicht.Das Problem ist, ob es sich um "Paketvariablen" oder "lexikalische Variablen" handelt.

Siehe die sehr gute Beschreibung der beiden in Perl "Coping with Scoping" verwendeten Variablensysteme:

http://perl.plover.com/FAQs/Namespaces.html

Paketvariablen sind globale Variablen und sollten daher aus allen üblichen Gründen (z. B. Fernwirkung) vermieden werden.

Das Vermeiden von Paketvariablen ist eher eine Frage des "korrekten Betriebs" oder "schwerer zu injizierende Fehler" als eine Frage der "Lesbarkeit".

In what cases does it matter $_ is a global variable?

Überall.

Die bessere Frage ist:

In what cases is $_ local()ized for me?

Es gibt einige Stellen, an denen Perl $ _ für Sie lokalisiert (), hauptsächlich foreach, grep und map.Alle anderen Orte erfordern, dass Sie es lokal () ize selbst, daher werden Sie einen potenziellen Fehler injizieren, wenn Sie dies unweigerlich vergessen.:-)

Andere Tipps

Der klassische Fehlermodus für die Verwendung von $_ (implizit oder explizit) als Schleifenvariable ist

for $_ (@myarray) {
  /(\d+)/ or die;
  foo($1);
}

sub foo {
  open(F, "foo_$_[0]") or die;
  while (<F>) {
    ...
  }
}

wobei, da die Schleifenvariable in for / foreach an das tatsächliche Listenelement gebunden ist, der while (<F>) @myarray mit aus den Dateien gelesenen Zeilen überschreibt.

$ _ entspricht der Benennung der Variablen wie in Ihrem zweiten Beispiel mit der Art und Weise, wie sie normalerweise verwendet wird.$ _ ist nur eine Verknüpfung des Standardvariablennamens für das aktuelle Element in der aktuellen Schleife, um beim Eingeben einer schnellen, einfachen Schleife beim Tippen zu sparen.Ich benutze eher benannte Variablen als die Standardvariablen.Es macht klarer, was es ist, und wenn ich eine verschachtelte Schleife ausführen muss, gibt es keine Konflikte.

Da $ _ eine globale Variable ist, können unerwartete Werte angezeigt werden, wenn Sie versuchen, den Wert eines vorherigen Codeblocks zu verwenden.Der neue Codeblock kann Teil einer Schleife oder einer anderen Operation sein, die ihre eigenen Werte in $ _ einfügt und das überschreibt, was Sie erwartet haben.

Das Risiko bei der Verwendung von $ _ besteht darin, dass es global ist (es sei denn, Sie lokalisieren es mit local $_). Wenn also eine Funktion, die Sie in Ihrer Schleife aufrufen, auch $ _ verwendet, können die beiden Verwendungen stören.

Aus Gründen, die mir nicht klar sind, hat mich das nur gelegentlich gebissen, aber ich lokalisiere normalerweise $ _, wenn ich es in Paketen verwende.

$_ ist nichts Besonderes, außer dass es der Standardparameter für viele Funktionen ist.Wenn Sie Ihren $_ explizit lexikalisch mit my versehen, verwendet perl die lokale Version von $_ anstelle der globalen.Daran ist nichts Seltsames, es ist genau wie bei jeder anderen benannten Variablen.

sub p { print "[$_]"; } # Prints the global $_
# Compare and contrast
for my $_ (b1..b5) { for my $_ (a1..a5) { p } } print "\n"; # ex1
for my $_ (b1..b5) { for       (a1..a5) { p } } print "\n"; # ex2
for       (b1..b5) { for my $_ (a1..a5) { p } } print "\n"; # ex3
for       (b1..b5) { for       (a1..a5) { p } } print "\n"; # ex4

Sie sollten von der Ausgabe leicht verwirrt sein, bis Sie feststellen, dass Perl den ursprünglichen Wert der Schleifenvariablen beim Verlassen der Schleife beibehält (siehe perlsyn ).

Beachten Sie ex2 oben.Hier verwendet die zweite Schleife den in der ersten Schleife deklarierten generischen Codacetagcode mit lexikalischem Gültigkeitsbereich.Subtil, aber erwartet.Auch dieser Wert bleibt beim Beenden erhalten, damit die beiden Schleifen nicht stören.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top