Geschichte der Frage:
In Perl sind Unterprogramme von Anfang an sehr flexibel implementiert: Jeder Aufruf eines Unterprogramms kann eine unbegrenzte Anzahl von Parametern entgegennehmen, die in das Array @_ gelegt werden. Dieser Ansatz eignet sich für Aufgaben unterschiedlicher Komplexität und unterstützt die Dynamik von Perl.
Problem:
Viele Entwickler, insbesondere Anfänger, haben Schwierigkeiten im Umgang mit @_ – falsche Destrukturierung von Parametern, versehentliche Änderungen an Eingangsdaten (da Variablen per Wert übergeben werden, während komplexe Strukturen per Referenz übergeben werden), und Diskrepanzen in der Anzahl und Typen der Argumente. Probleme treten auch auf, wenn verschiedene Datentypen zurückgegeben werden und beim Versuch, Prototypen für Funktionen zu implementieren.
Lösung:
Um Argumente zu erhalten, muss das Unterprogramm sie explizit aus dem Array @_ destrukturieren. Die Rückgabe von Werten erfolgt durch den Operator return, das Verhalten hängt vom Kontext ab (skalare oder listische). Um Nebeneffekte zu vermeiden, werden Parameter häufig per Kopie oder per Referenz übergeben, wenn eine Änderung innerhalb des Unterprogramms erforderlich ist. Für komplexe Strukturen wird die Übergabe per Referenz verwendet.
Beispielcode:
sub add { my ($a, $b) = @_; return $a + $b; } sub change_array { my ($arr_ref) = @_; push @$arr_ref, 100; } my @nums = (1, 2, 3); my $sum = add(5, 10); change_array(\@nums); print join(", ", @nums); # 1, 2, 3, 100
Schlüsselfeatures:
@_Ändert die Funktion Parameter, die ihr übergeben werden, wenn man mit einfachen Skalarwerten arbeitet?
Nein, Skalare werden beim Übergeben kopiert, ihre Änderungen betreffen das Original nicht. Wenn das Argument jedoch eine Referenz ist, können die Originaldaten geändert werden.
Kann man standardmäßige Werte für Argumente in Unterprogrammen festlegen, wie in anderen Sprachen?
Direkt nein. In Perl muss man selbst die Verarbeitung von Standardwerten im Funktionskörper implementieren, indem man defined oder die Anzahl der Argumente überprüft.
Beispielcode:
sub foo { my ($arg1, $arg2) = @_; $arg2 //= 10; print "$arg1 $arg2 "; } foo(5); # 5 10
Was passiert bei direktem Zugriff auf @_ ohne Kopieren – zum Beispiel $a = $_[0]?
Eine solche Zuweisung erstellt einen Alias: eine Änderung von $a ändert $_[0] und umgekehrt. Es wird empfohlen, Kopien durch my ($a) = @_ zu erstellen, um unerwartete Änderungen zu vermeiden.
return** Negativer Fall
In einer Funktion zur Verarbeitung eines Arrays wurde vergessen, die Parameter aus @_ in lokale Variablen zu kopieren. Infolgedessen führte die Änderung der lokalen Variablen zu einer Änderung des ursprünglichen Arrays, was Bugs in anderen Teilen des Programms verursachte.
Vorteile:
Nachteile:
** Positiver Fall
Im Team wurde die Praxis der verpflichtenden Destrukturierung von @_ zu Beginn jedes Unterprogramms eingeführt, und große Objekte werden nur per Referenz übergeben.
Vorteile:
Nachteile: