In Perl zijn hashes (associatieve arrays) een krachtig hulpmiddel voor het opslaan van sleutel-waardeparen. Het werken met hen vereist echter voorzichtigheid, vooral bij gelijktijdig doorlopen en wijzigen van de structuur. Gemiste details kunnen leiden tot fouten die moeilijk te diagnosticeren zijn.
Associatieve arrays werden geïntroduceerd in de vroege versies van Perl (Perl 1/2), waardoor ze een van de eerste talen waren met volledige ondersteuning voor hashes op kernniveau. Na verloop van tijd kwamen er extra mogelijkheden: iteratie via each, verwijdering (delete), massale transformatie (map, grep) en het omgaan met wijzigingen in grootte/inhoud tijdens het doorlopen.
Het doorlopen van een hash en tegelijkertijd de inhoud ervan wijzigen, vooral het verwijderen van elementen, kan leiden tot onverwachte effecten: het overslaan van elementen, het opnieuw doorlopen van dezelfde sleutels of zelfs een oneindige lus. Bovendien is de volgorde van het doorlopen van sleutels niet gegarandeerd en kan deze variëren tussen versies van Perl.
each gebruikt, omdat de interne cursor dan verstoord raaktkeys, en loop vervolgens met een aparte lus door deze lijst en verwijder elementenwhile (my ($k, $v) = each %h) voor normale iteratie, maar combineer dit niet met delete binnen de lus als je geen verrassingen wiltVoorbeeld van veilige verwijdering van elementen:
my %h = (a=>1, b=>2, c=>3); for my $k (keys %h) { delete $h{$k} if $h{$k} == 2; }
Voorbeeld van een onjuiste benadering:
while (my ($k, $v) = each %h) { delete $h{$k}; # Dit kan leiden tot het overslaan van sleutels }
Belangrijke kenmerken:
each is gevoelig voor wijzigingen in de structuur tijdens het werkenIs het veilig om elementen uit de hash te verwijderen binnen een while (each %h) lus?
Nee, dit kan leiden tot het overslaan van delen van de hash door het resetten van de interne iteratiecursor.
Wat gebeurt er met de volgorde van de sleutels na het verwijderen van elementen uit de hash?
De volgorde is niet gegarandeerd en kan veranderen. Bovendien kan de volgorde van het doorlopen tussen programma's op dezelfde Perl verschillen.
Kun je de waarde van een hash-element wijzigen tijdens iteratie via each?
Ja, het wijzigen van de waarde (maar niet de structuur) is veilig.
Voorbeeld:
while (my ($k, $v) = each %h) { $h{$k} = $v + 10; }
Het gebruik van verwijdering van elementen via each in één lus:
my %h = (a=>1, b=>2, c=>3); while (my ($k, $v) = each %h) { delete $h{$k} if $v == 1; }
Voordelen:
Nadelen:
Het maken van een lijst van sleutels voor verwijdering:
my %h = (a=>1, b=>2, c=>3); for my $k (keys %h) { delete $h{$k} if $h{$k} == 1; }
Voordelen:
Nadelen: