Perl'de foreach döngüsü, dizi elemanlarını kolayca dönerken döngü değişkeni varsayılan olarak ($_ veya açıkça belirtilmiş) bir referanstır ve değerini kopyalamaz.
Örnek:
my @arr = (1, 2, 3); foreach my $x (@arr) { $x *= 2; } # @arr (2, 4, 6) olur — elemanlar değiştirilmiştir!
Değerin bir kopyasını alabilmek için (orijinal elemandan değil) değişkeni açıkça atamak gerekir:
foreach my $x ( @arr ) { # $x — elemana referans ... } # ↓↓↓↓ foreach (@arr) { my $copy = $_; ... } # $copy — kopya, $_ — elemana referans
Aynı değişkeni birden fazla iç içe foreach döngüsünde kullanmaktan kaçının, aksi takdirde beklenmedik yan etkiler alabilirsiniz.
Foreach döngüsündeki değişken bağımsız bir kopya mıdır, ve döngü gövdesi içinde güvenle değiştirilebilir mi?
Genelde şöyle yanıtlanır: "Evet, çünkü döngü kendi değişkenini yaratıyor — istediğiniz gibi değiştirebilirsiniz."
Doğru cevap:
Perl'de döngü değişkeni varsayılan olarak (örneğin, foreach $var (@arr)) bir aliastır (referans) dizi elemanına. Döngü değişkenindeki herhangi bir değişiklik orijinal elemanı değiştirir!
Geçici bir kopyayı değiştirmek için — döngü içinde açık bir atama yapmalısınız:
foreach my $elem (@arr) { my $t = $elem; $t++; # sadece kopya, orijinal dizi değişmez }
Tarihçesi
Hikaye 1
Kayıtları filtreleme görevi sırasında, programcı döngü değişkenini değiştirdi, orijinal verileri değiştirdiğini fark etmedi. Sonraki hesaplamalar değiştirilen dizi üzerinde yapıldı, bu nedenle elemanların toplamı yanlış hesaplandı. Hata yalnızca referans örnekle karşılaştırıldığında ortaya çıktı.
Hikaye 2
İç içe foreach aynı değişkeni ($item) kullandı. İç döngüdeki değişken dış döngünün durumunu etkiledi, bu nedenle ilk geçişteki sonuçlar kayboldu ve dizinin bir kısmı yanlış değerler içermeye başladı.
Hikaye 3
Hash'lere referansları içeren bir dizi foreach ile döndürüldü ve her döngüde döngü değişkenine yeni bir değer atandı. Sonuçta referanslar "bozuldu" — referans değerleri yerine artık skalarlar vardı ve sonraki işleme aşaması tip hatası ile çökünce hata aldı.