programowanieProgramista Full-stack

Opisz cykl foreach w Perl: czym różni się praca z kopiami elementów tablicy od ich oryginałów, jakie pułapki mogą wystąpić przy używaniu zmiennej cyklu?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

W Perl cykl foreach umożliwia wygodne iterowanie przez elementy tablicy, przy czym zmienna cyklu domyślnie ($_, lub jawnie wskazana) odnosi się do elementu tablicy, a nie kopiuje jego wartości.

Przykład:

my @arr = (1, 2, 3); foreach my $x (@arr) { $x *= 2; } # @arr równa się (2, 4, 6) — elementy zostały zmienione!

Aby uzyskać właśnie kopię wartości (a nie odniesienie do oryginalnego elementu), należy jawnie przypisać zmienną:

foreach my $x ( @arr ) { # $x — odniesienie do elementu ... } # ↓↓↓↓ foreach (@arr) { my $copy = $_; ... } # $copy — kopia, $_ — odniesienie do elementu

Nie należy używać tej samej zmiennej w kilku zagnieżdżonych cyklach foreach, w przeciwnym razie można uzyskać nieoczekiwane efekty uboczne.


Pytanie z pułapką

Czy zmienna w cyklu foreach jest niezależną kopią, i czy można ją bezpiecznie zmieniać wewnątrz ciała cyklu?

Zazwyczaj odpowiada się: "Tak, ponieważ cykl tworzy zmienną — można zmieniać ją w dowolny sposób."

Poprawna odpowiedź:

W Perl zmienna cyklu domyślnie (na przykład, foreach $var (@arr)) jest aliasem (odniesieniem) do elementu tablicy. Jakakolwiek zmiana zmiennej cyklu prowadzi do zmiany oryginalnego elementu!

Aby zmieniać tymczasową kopię — należy wykonać jawne przypisanie wewnątrz cyklu:

foreach my $elem (@arr) { my $t = $elem; $t++; # tylko kopia, oryginalna tablica nie zmienia się }

Historia


Historia 1

W zadaniu z filtrowaniem rekordów programista zmodyfikował zmienną swojego cyklu, nie zdając sobie sprawy, że zmienia oryginalne dane. Kolejne obliczenia odbywały się na zmodyfikowanej tablicy, przez co suma elementów była obliczana błędnie. Błąd ujawnił się dopiero przy porównaniu z referencyjną próbą.


Historia 2

Zagnieżdżony foreach używał tej samej zmiennej ($item). Zmienna wewnętrznego cyklu nadpisała stan zewnętrznego, przez co utracono wyniki pierwszego przebiegu, a część tablicy okazała się mieć nieprawidłowe wartości.


Historia 3

Tablica odniesień do hashy była iterowana przez foreach, a w każdym cyklu zmiennej cyklu przypisywana była nowa wartość. W rezultacie odniesienia zostały "zepsute" — zamiast wartości referencyjnych teraz stały skalary, a następny etap przetwarzania zakończył się błędem typu.