2012-06-01 20 views

Odpowiedz

15

Nie jesteś iteracji nad hash, jesteś iteracji na listę kluczy zwracanych przez keys zanim jeszcze rozpoczął zapętlenie ponieważ

for my $key (keys %$hash_ref) { 
    ... 
} 

jest mniej więcej taka sama jak

my @anon = keys %$hash_ref; 
for my $key (@anon) { 
    ... 
} 

Usunięcie z hasza nie powoduje żadnych problemów.


each, z drugiej strony, ma iterować mieszania. Za każdym razem, gdy się go nazywa, each zwraca inny element. Jednak nadal jest bezpieczny dla obecnego elementu!

# Also safe 
while (my ($key) = each(%$hash_ref)) { 
    ... 
    delete $hash_ref->{$key}; 
    ... 
} 

Jeśli dodać lub usunąć elementy hash jest podczas iteracji nad nim, wpisy mogą zostać pominięte lub powielane - więc nie rób tego. Wyjątek: Zawsze bezpiecznie można usunąć element, który został ostatnio zwrócony przez każde()

+0

Sformułowanie "w obecnej wersji" trochę mnie przeraża, ponieważ wydaje się, że jest tam miejsce na zmianę implementacji, tak aby było nie jest już bezpieczny. Nie będę polegał na tym, ale wtedy nie użyłbym 'each()' albo - klawisze foreach są w porządku. – LeoNerd

+0

@LeoNerd, starszy Perl (co najmniej 5,10) mówi "zawsze można bezpiecznie usunąć ...". Z oczywistych powodów ze względu na kompatybilność, wątpię, aby to się zmieniło bez wprowadzenia jakiejś "funkcji użycia" lub innej podobnej pragmy. –

+1

, który dodał, że "w obecnej realizacji"? nie zawsze tam było i nie powinno tam teraz być, chyba że istnieje naprawdę dobry powód. update: Wydaje się, że już tam nie ma. – ysth

3

Jest bezpieczny, ponieważ keys %hash zawiera całą listę raz, przed rozpoczęciem iteracji. foreach kontynuuje pracę nad tą wstępnie wygenerowaną listą, bez względu na to, co zmienisz wewnątrz rzeczywistego skrótu.

Zżera pamięć, ponieważ przechowujesz całą listę, dopóki nie skończysz.

Powiązane problemy