ProgrammatieFull-stack ontwikkelaar

Beschrijf de foreach-lus in Perl: wat is het verschil tussen werken met kopieën van array-elementen en hun originelen, welke valkuilen zijn er bij het gebruik van de lusvariabele?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

In Perl stelt de foreach-lus u in staat om eenvoudig de elementen van een array te doorlopen, waarbij de lusvariabele standaard ($_, of expliciet aangegeven) verwijst naar het array-element en niet zijn waarde kopieert.

Voorbeeld:

my @arr = (1, 2, 3); foreach my $x (@arr) { $x *= 2; } # @arr is (2, 4, 6) — elementen zijn gewijzigd!

Om daadwerkelijk een kopie van de waarde te krijgen (en niet een verwijzing naar het originele element), moet u de variabele expliciet toewijzen:

foreach my $x ( @arr ) { # $x — verwijzing naar het element ... } # ↓↓↓↓ foreach (@arr) { my $copy = $_; ... } # $copy — kopie, $_ — verwijzing naar het element

Het is niet aan te raden om dezelfde variabele te gebruiken in meerdere geneste foreach-lussen, anders kunnen onverwachte bijeffecten optreden.


Trickvraag

Is de variabele in de foreach-lus een onafhankelijke kopie, en kan deze veilig binnen de lusschaal worden gewijzigd?

Meestal antwoorden mensen: "Ja, want de lus creëert zelf de variabele — je kunt deze naar wens wijzigen."

Juiste antwoord:

In Perl is de lusvariabele standaard (bijvoorbeeld, foreach $var (@arr)) een alias (verwijzing) naar het array-element. Elke wijziging aan de lusvariabele leidt tot een wijziging van het originele element!

Om een tijdelijke kopie te wijzigen — maak een expliciete toewijzing binnen de lus:

foreach my $elem (@arr) { my $t = $elem; $t++; # alleen kopie, originele array verandert niet }

Geschiedenis


Geschiedenis 1

Bij een taak om records te filteren, wijzigde de programmeur zijn lusvariabele, niet wetende dat hij de originele gegevens wijzigde. Latere berekeningen gebeurden op de gewijzigde array, waardoor de som van de elementen onjuist werd berekend. De fout kwam alleen aan het licht bij vergelijking met een referentiesample.


Geschiedenis 2

Geneste foreach gebruikte dezelfde variabele ($item). De variabele van de binnenste lus overschreef de status van de buitenste, waardoor de resultaten van de eerste doorgang verloren gingen en een deel van de array incorrecte waarden had.


Geschiedenis 3

Een array van verwijzingen naar hashes werd doorlopen via foreach, en in elke lus werd de lusvariabele een nieuwe waarde toegewezen. Het resultaat was dat de verwijzingen "gebroken" waren — in plaats van verwijzingswaarden stonden er nu scalars, en de volgende verwerkingsfase viel met een typefout.