In Perl nehmen Unterprogramme Argumente über die spezielle Array-Variable @_ entgegen, in die automatisch alle übergebenen Parameter eingefügt werden. Eine Besonderheit von Perl ist, dass Parameter durch Referenzen in @_ gelangen, was bedeutet, dass Änderungen an den Elementen innerhalb der Funktion deren Werte außerhalb verändern.
Um unerwartete Änderungen der übergebenen Daten zu vermeiden, sollten Parameter in Variablen kopiert werden:
sub sum { my ($a, $b) = @_; return $a + $b; }
Perl-Funktionen geben immer eine Liste von Werten zurück, und das Ergebnis der Funktion ist die zuletzt berechnete Liste oder ein expliziter return-Operator.
sub minmax { my ($x, $y) = @_; return ($x < $y ? $x : $y, $x > $y ? $x : $y); } my ($min, $max) = minmax(4, 7); # $min = 4; $max = 7
Wenn die Funktion im skalaren Kontext aufgerufen wird, gibt sie die Anzahl der zurückgegebenen Elemente zurück, wenn das Ergebnis nicht in einen Skalar eingeschlossen wird.
Wie übergibt man eine große Anzahl von Variablen an eine Perl-Funktion, um versehentliche Änderungen der ursprünglichen Variablen zu vermeiden?
Unbewusst antworten viele: "Man muss die Argumente einfach wie gewohnt in Variablen kopieren!"
Richtige Antwort:
Das Kopieren funktioniert nur für Skalarwerte. Wenn Sie mit Arrays oder Hashes arbeiten, verwenden Sie Referenzen, um die Datenübergabe explizit zu steuern und versehentliche Verweise zu vermeiden:
sub modify { my ($arr_ref) = @_; push @$arr_ref, 'new'; # ändert das ursprüngliche Array } my @data = (1, 2, 3); modify(\@data); # jetzt @data = (1, 2, 3, 'new')
Geschichte
Geschichte 1
In einem großen Skript zur Verarbeitung von Berichten änderte eine interne Funktion die Werte der Array-Elemente, die aus dem Hauptprogramm übergeben wurden. Infolgedessen wurden die ursprünglichen Daten nach der Ausführung der Funktion verfälscht. Der Fehler lag darin, dass der Autor der Funktion keine Kopien der Eingabewerte machte, in der Annahme, dass die Änderungen lokal wären – was für @_ mit Arrays jedoch nicht zutrifft.
Geschichte 2
Bei der Migration von Skripten aus Perl 4 (wo Variablen anders kopiert wurden) stieß das Team auf das Problem, dass die Übergabe von verschachtelten Hashes zu unerwarteten Daten "lecks" zwischen den Aufrufen von Unterprogrammen führte – Veränderungen an Feldern eines Hashs in einer Funktion beeinflussten andere Teile des Codes. Der Grund war die Referenz auf den Hash in der Liste @_.
Geschichte 3
Ein Entwickler implementierte eine Funktion, die ein Array von Ergebnissen zurückgibt, verwendete jedoch an der aufrufenden Stelle einen skalarischen Kontext:
$count = func(@params);. Es wurde erwartet, dass der Variablen der Wert des ersten zurückgegebenen Elements zugewiesen wird, tatsächlich war jedoch in$countdie Anzahl der Elemente in der Liste, was zu Verzögerungen bei den Berechnungen und Verwirrung führte.