Builder

web application developer blog

PHP generator function – yield

Python’u yada C#’ı iyi bilenler, daha başlığı okuduklarında, aa PHP’de de mi yield var demişlerdir. Evet PHP de de yield var ama 5.5 versiyonundan itibaren var. Yani daha yeni eklendi sayılır. yield’i yeni duyanlar için örneklerle yield nedir nasıl kullanılır anlatayım. Bunu yaparken en sevdiğim eğitim metodu olan “Bilinenden bilinmeyene” metodunu kullanacağım.

Efendim, PHP de fonksiyon yazmayı biliyoruz. Fonksiyonların herhangi biryerde sonlanması ve/veya geriye değer döndürmesi için de return  kullanıdığımızı biliyoruz. İşte yield tıpkı return gibi geriye değer döndürür ama return‘den farklı olarak fonksiyonu sonlandırmaz. Özetle değer üretir. Bu  nedenle de yield‘li fonksiyonlara üreteç (generator) denir.

Çoğu programcı için teroik tanımlamalar laf kalabilığından ibarettir. Örneksiz öğrenme olmaz. Hemen örnek verelim.

Bir çift sayı üreteci oluşturalım:

function evenGenerator($start=0,$max=2){
    $n= ($start % 2 == 0) ? $start : $start+1; //Eğer başlangıç tek ise başlangıcın bir fazlası ilk sayısı n olsun
    while($n<$max){ // son sayıdan küçük olduğu sürece üretim devam etsin
        yield $n; // üretilen sayıyı döndürelim ama işlev sonlanmıyor. 
        $n+=2; //Sonraki sayı üretiliyor
    }
}

echo "2-100 arasındaki çift sayılar :<br/>";
foreach(evenGenerator(2,100) as $n){
    echo $n."<br/>";
}

yani burada amaç kodu daha fazla parçalayarak daha basit yapılar elde etmek. Böylece anlaşılabilirliği artırmak. Elbette yield çif sayı üretmekten çok daha karmaşık işler için kullanılmalı.

 

Bir diğer örneği projecteuler.org’un 3 numaralı problemi üzerinde verelim. Problemi daha önce şu blog‘da çözmüştük zaten. Aynı mantıkla generator fonksiyon oluşturacak olursak:

function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}

function isPrime($n){
    if($n<2)
        return false;
    for($i=2; $i<=sqrt($n); $i++){
        if($n % $i == 0)
            return false;
    }
    return true;
}
function primes($n=2, $max=3){
    while($n<$max){
        if(isPrime($n)) yield $n;
        $n++;
    }
}
$startTime = microtime_float();
$target = (float)600851475143;
$maxPrimeFactor =0;
$sqrtTarget = sqrt($target);
foreach(primes(2,$sqrtTarget) as $n){
    if(bcmod($target, $n) == 0){
        $maxPrimeFactor = $n;
    }
}
echo $maxPrimeFactor."\n";
$executionTime = microtime_float()- $startTime;
echo "Execution Time: ".$executionTime;

Şimdi programın çıktısına bakalım:

6857
Execution Time: 21.8440721035

Çalışma süresini, daha önceki çözümümüz ile kıyasladığımızda arada bariz bir performans kaybı olduğunu görüyoruz. Yani PHP’de yield “henüz” kullanılabilecek kadar gelişmiş değil.

Şurada PHP’nin kendi sitesindeki bir üreteç fonksiyon örneği ve performans karşılaştırması var.

Bizim ise elimizden gelen tek şey, PHP 7 ile birlikte daha performanslı üreteç fonksiyon geliştirebilmeyi ümidetmek!

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir