Perl'de hash'ler (ilişkisel diziler) anahtar-değer çiftlerini saklamak için güçlü bir araçtır. Ancak, bunlarla çalışmak dikkat gerektirir, özellikle yapı üzerinde eşzamanlı olarak yineleme ve değişiklik yaparken. Burada gözden kaçan ayrıntılar, teşhisi zor hatalara yol açabilir.
İlişkisel diziler, Perl'in ilk sürümlerinde (Perl 1/2) uygulanmış olup, onları çekirdek seviyede hash desteği olan ilk dillerden biri haline getirmiştir. Zamanla ek özellikler eklendi: each ile yineleme, silme (delete), toplu dönüştürme (map, grep) ve geçiş sırasında boyut/ içerik değişikliğiyle başa çıkma.
Bir hash'i tararken ve aynı anda içeriğini değiştirirken, özellikle elemanları silmek, beklenmedik etkilere yol açabilir: elemanların atlanması, aynı anahtarlar üzerinde tekrar geçiş yapılması veya hatta sonsuz döngü. Ayrıca, anahtarların geçiş sırası garanti edilmez ve Perl sürümleri arasında değişiklik gösterebilir.
each kullanıyorsanız, yineleme sırasında hash'i değiştirmeyin; çünkü içsel kursor bozulur.keys ile toplayın, ardından ayrı bir döngüde üzerinden geçerek silin.while (my ($k, $v) = each %h) kullanarak normal bir geçiş yapın, ancak döngü içinde delete ile birleştirmeyin, aksi takdirde beklenmedik durumlarla karşılaşabilirsiniz.Doğru eleman silme örneği:
my %h = (a=>1, b=>2, c=>3); for my $k (keys %h) { delete $h{$k} if $h{$k} == 2; }
Yanlış yaklaşım örneği:
while (my ($k, $v) = each %h) { delete $h{$k}; # Bu anahtarların atlanmasına neden olabilir }
Anahtarların geçişiyle ilgili önemli noktalar:
each kullanarak yapılan yineleme, çalışma sırasında yapıdaki değişikliklere duyarlıdır.while (each %h) döngüsü içinde hash'ten elemanları güvenle silmek mümkün mü?
Hayır, bu içsel yineleme kursörünün sıfırlanması nedeniyle hash'in parçalarının atlanmasına neden olabilir.
Hash'ten elemanlar silindikten sonra anahtarların sırasına ne olur?
Sıra garanti edilmez ve değişebilir. Ayrıca, aynı Perl'de çalıştırılan programlar arasında geçiş sırası farklı olabilir.
Yineleme sırasında each ile hash elemanının değerini değiştirmek mümkün mü?
Evet, değer değişikliği (ancak yapı değişikliği değil) güvenlidir.
Örnek:
while (my ($k, $v) = each %h) { $h{$k} = $v + 10; }
Bir döngü içinde each ile eleman silme:
my %h = (a=>1, b=>2, c=>3); while (my ($k, $v) = each %h) { delete $h{$k} if $v == 1; }
Artıları:
Eksileri:
Silinecek anahtarlar için liste oluşturma:
my %h = (a=>1, b=>2, c=>3); for my $k (keys %h) { delete $h{$k} if $h{$k} == 1; }
Artıları:
Eksileri: