Historie der Frage:
Perl hat von Anfang an großen Wert auf die Arbeit mit Arrays und Listen von Daten gelegt. Funktionen wie map, grep und die foreach-Schleife ermöglichen es dem Programmierer, Sammlungen prägnant und effizient zu verarbeiten und mächtige Muster der funktionalen Programmierung in einem Ausdruck zu implementieren.
Problem:
Viele Anfänger in Perl verwirren die Situationen, wann map, wann foreach oder grep verwendet werden sollte, was zu einer falschen Auswahl des Werkzeugs und zu einer Verringerung der Leistung oder Lesbarkeit des Codes führt. Darüber hinaus führt Unaufmerksamkeit gegenüber Nebeneffekten (side effects) im Körper solcher Ausdrücke zu schwer zu debuggen Fehlern.
Lösung:
Die richtige Wahl des Traversierungswerkzeugs hängt von der Aufgabe ab:
map — wird verwendet, um die Elemente einer Liste zu transformieren und eine neue Ergebnisliste zu erstellen.grep — filtert die Elemente der Ausgangsliste nach einem definierten Kriterium.foreach — wird für Nebeneffekte und iterative Verarbeitung verwendet, häufig ohne Rückgabewert.Beispielcode:
my @numbers = (1, 2, 3, 4, 5); my @squares = map { $_ * $_ } @numbers; # [1, 4, 9, 16, 25] my @even = grep { $_ % 2 == 0 } @numbers; # [2, 4] foreach my $n (@numbers) { print "Zahl: $n "; # gibt jedes Element aus }
Wichtige Merkmale:
map und grep arbeiten im Listenmodus und geben eine neue Liste zurück.foreach erstellt keine neue Liste, sondern durchläuft einfach die Elemente.map oder grep sind nicht empfohlen.Kann man sicher ein Array innerhalb des Körpers von map oder grep ändern?
Nein, denn Perl durchläuft eine Liste von Kopien der Elemente, aber eine Modifikation des ursprünglichen Arrays kann zu unerwarteten Ergebnissen oder sogar zu einer unendlichen Schleife führen.
Was passiert, wenn man return im Körper von map oder grep verwendet?
Ein return-Ausdruck innerhalb eines anonymen Blocks führt zum Verlassen der umgebenden Unterroutine und nicht nur des Körpers von map/grep, was gefährlich für die Programmlogik ist.
Beispielcode:
sub beispiel { my @data = (1, 2, 0, 4); my @result = map { return "Oops" if $_ == 0; $_+1 } @data; # verlässt beispiel bei 0 }
Warum sollte man map nicht nur für Nebeneffekte verwenden?
Weil map zum Generieren neuer Listen gedacht ist und alle ihre Elemente sofort berechnet werden. Für Nebeneffekte ist es besser, foreach zu verwenden – das ist lesbarer und erfordert keine Speicherung des Ergebnisses.
Im Projekt wurde map verwendet, um in das Log zu schreiben, ohne sich um die zurückgegebene Liste zu kümmern.
Vorteile:
Nachteile:
Es wurde foreach verwendet, um in das Log zu schreiben, und map nur zur Generierung neuer Listen, ohne die Muster zu vermischen.
Vorteile:
Nachteile: