Perl'de anonim alt programlar ve closure'lar desteklenmektedir. Anonim alt programlar, isim olmadan sub ile tanımlanır ve kodun bir referansını döndürür. Closure, oluşturuldukları anda var olan değişkenleri içeren leksik bir alanı 'yakalar' ve bir alt programdır.
Anonim alt program ve closure örneği:
sub make_incrementer { my $inc = shift; return sub { $_[0] + $inc }; } my $inc10 = make_incrementer(10); print $inc10->(5); # 15'i yazdırır
Closures, fonksiyon fabrikaları, jeneratörler ve callback'ler oluşturmak için aktif olarak kullanılır (örneğin, map/grep, olay işleyicileri gibi).
Önemli bir nokta: Eğer bir closure, kendisine (doğrudan veya yapılar aracılığıyla) işaret eden değişkenlere işaret ediyorsa, dairesel referans oluşur ve bellek sızıntısına neden olabilir.
Closure içinde kapatılan değişkenler ne zaman serbest bırakılır?
myileourdeğişkenleri için farklılık var mı?
Cevap: Closure içinde kapatılan my değişkenleri, closure'a en az bir referans olduğu sürece yaşamaya devam eder. Fonksiyon tamamlandığında serbest bırakılmazlar, yaşam süreleri — tüm closure'ın yaşam süresidir. our değişkenler için böyle bir davranış yoktur — tüm closure'lar için erişilebilirler ve program sona erdiğinde serbest bırakılırlar. Closure'ı silmeyi unutarak bellek sızıntısına neden olabilirsiniz.
Sorun örneği:
my $cref; { my $val = 5; $cref = sub { $val++ }; } # $val hala mevcut, $cref canlı olduğu sürece
Hikaye
Sunucu uygulamasında her kullanıcı için callback için bir closure bağlamı oluşturuluyordu. Ancak closure, kullanıcı yapısına da referans veriyordu, bu da dairesel referansa neden oluyordu. Bu nedenle, garbage collector, kullanıcı nesnelerini logout sonrasında bile temizlemiyordu — bellek sızıntıları üstel bir şekilde artıyordu.
Hikaye
Olayları arka planda işlemek için bir demon uygulamasında kapalı sayaç değişkenlerine sahip closures kullanıldı, ancak referans verdikleri dizileri sıfırlamayı unuttular. Sonuç olarak — birkaç unutulan closure nedeniyle eski mesaj verileri birikti, demon arızalanmadan önce yığılı bellek temizliği yapmak zorunda kaldık.
Hikaye
Bir geliştirici, closure içinde
ourdeğişkenini kullanmaya çalıştı, 'kapalı' bir davranış bekliyordu — ancak tüm closures ortak bir değişkeni paylaştı, bu da paralel yürütme sırasında veri yarışlarına neden oldu. Hata, farklı parametrelerle aynı anda çalışan kullanıcılar arasında ortaya çıktı (hatalı hesaplamalar).