Soru tarihi:
Tembel listeler (lazy lists) fikri, muhtemel sonsuz dizilerin veya ertelenmiş hesaplamaların işlenmesi için birçok programlama dilinde uygulanmaktadır. Perl'de, Python'daki yield gibi yerleşik jeneratör desteği yoktur, ancak tembel veri yapılarını kapamalar, yineleyiciler ve özel modüller (örneğin, Iterator::Simple) kullanarak uygulamak mümkündür.
Sorun:
Temel zorluk, fonksiyon/kapanış çağrıları arasında durumu etkili bir şekilde iletmek ve belleği serbest bırakmaktır. Değişkenlerin yeniden kullanılması, verilere erişimin kaybolması, ertelenmiş veya çok erken hesaplamalar genellikle hatalara veya bellek sızıntısına yol açar.
Çözüm:
İç durumunu kapsülleyen anonim alt programlar (closures) kullanmak. Bu yaklaşım, ihtiyaç duyulduğunda jeneratörler oluşturmayı mümkün kılar. Dış modüllerden yararlanılabilir, örneğin, Iterator::Simple veya kendi tembel jeneratörünüzü yazabilirsiniz.
Kod örneği:
my $counter = lazy_counter(5); while (my $v = $counter->()) { print "$v "; } sub lazy_counter { my $max = shift; my $current = 1; return sub { return undef if $current > $max; return $current++; }; }
Anahtar özellikler:
İteratörün iç durumunu iç içe geçen bir sözcük değişkeninde saklamak ne kadar güvenli? Bu bellek yönetimini nasıl etkiler?
Kapanışın iç durumu, kapanışa bir referans sürdüğü sürece serbest bırakılmaz. Eğer kapanış tesadüfen büyük diziler veya dış yapılara referanslar içeriyorsa, bu bellek sızıntısına yol açar.
Birden fazla tembel liste veya jeneratör arasında kontrolü doğrudan, yield desteği olan dillerdeki gibi iletebilir miyiz?
Perl'de, alt program "dondurulamadığı" için yield'e benzer bir kontrol geçişi yapmak mümkün değildir. Her jeneratör güçlü bir şekilde kendi kapanış ve çağrı yığını tarafından kontrol edilir. Karmaşık senaryolar için Coro veya AnyEvent gibi modüller kullanmak mantıklıdır.
Kapanış ile normal bir döngü kullanarak pozisyonu dış bir değişkende saklamak arasındaki fark nedir?
Kapanış, durumu kapsüller ve dışarıdan kazara değişiklikleri önler. Dış bir gösterici kullanılırsa, muhtemel paralel kullanım mümkün olmayabilir veya senkronizasyon hatalarına yol açabilir.
Bir mühendis, global bir değişken üzerinden kendi yaptıkları bir iteratör yazar, kapsam özelliklerini unutuyor. Programın farklı bölümlerinde aynı sayacı kullanıyor, bu da sayacın "ilerlemesine" ve döngü mantığını bozmasına sebep oluyor.
Artılar:
Eksiler:
Durumu kapsülleyen bir kapanış kullanılıyor. Jeneratör, programın herhangi bir yerinde iletilebilir, aynı anda birden fazla örneği çalıştırabilir.
Artılar:
Eksiler: