PHP'de: “getiri”, “verim”, “verim” ile hem verimi hem de getiriyi aynı işlevde karıştırmak arasındaki fark nedir?


10

Ben ve anladım kadar arasındaki fark returnve yieldnet görünüyordu yield fromve her ikisini de returnve yieldaynı işlevi birleştirmek imkanı !

Benim anlayış returnher şeyin sonra oldu değil idam, doğru mu?

Ancak:

function generate(): iterable {
    return [1, 2, 3];
}

foreach (generate() as $value) {
    echo $value;
}

Yapımcı: "123"

Ancak aşağıdakiler:

function generate(): iterable {
    return [1, 2, 3];
    yield;
}

foreach (generate() as $value) {
    echo $value;
}

Hiçbir şey üretmez! Yani bu verimin yapıldığı anlamına mı geliyor?

Bu bir hata mı?


1
var_dump(generate()->GetReturn());
AbraCadaver

Yanıtlar:


10

Return

Arayan kişiye benzersiz bir değer verir.

Yield

Mevcut işlevi / yöntemi Generator, benzersiz bir değerden daha fazlasını üretecek olan a değerini döndürmek için dönüştürün : her zaman yieldtetiklendiğinde, değeri geleneksel olarak bir foreachdöngü kullanarak arayana birer birer verir .

Yield + Return

Jeneratörler, değer üretmenin yanı sıra, benzersiz bir döndürülen değer de sağlayabilir. Bu değer, jeneratörün etrafındaki döngünün bir parçası olmayacak, buna Generator::getReturn()yöntem kullanılarak erişilmelidir .

Return + Yield

Bu bir hata olarak görülebilir, ancak değildir.

Bunlar iki aşamadır:

  1. Koddan bayt koduna : bu aşamada, generate()fonksiyonun yieldanahtar kelimeyi içerdiği görülür , bu nedenle a üretilir Generator.
  2. Yürütme : Çünkü returnönce olduğu yieldgibi, jeneratörün herhangi bir değer üretme şansı yoktur. Ancak, [1, 2, 3]dizi ile alınabilir Generator::getReturn().

Açıklamalı tam bir örnek:

// Generate integers 1 and 2
function generateIntegers1And2(): Generator {
    yield 1;                                  // <--+   <--+   <--+
    yield 2;                                  //  <-+    <-+    <-+
}                                             //    |      |      |
                                              //    |      |      |
foreach (generateIntegers1And2() as $value) { //    |      |      |
    var_dump($value); // Shows 1, then 2          ->*      |      |
}                                                       // |      |
                                                        // |      |
function generateOuterYield(): Generator {              // |      |
    // Yields the generator *itself* returned by           |      |
    // generateIntegers1And2() not the actual values       |      |
    // generated by it.                                    |      |
    // This means we are producing here a generator        |      |
    // of generator of integers.                           |      |
    yield generateIntegers1And2();          // <-+         |      |
}                                             // |         |      |
                                              // |         |      |
foreach (generateOuterYield() as $value) {    // |         |      |
    var_dump($value);                       // ->*         |      |
    // The two levels of imbrication means we have         |      |
    // to loop once more to actually consume               |      |
    // generateIntegers1And2                               |      |
    foreach ($value as $val) {                          // |      |
        var_dump($val); // Shows 1, then 2               ->*      |
    }                                                          // |
}                                                              // |
                                                               // |
// A generator can just be returned as-is:                        |
function generateOuterReturn(): Generator {                    // |
    return generateIntegers1And2();                            // |
}                                                              // |
                                                               // |
// it doesn't change the way it is consumed                       |
foreach (generateOuterReturn() as $value) {                    // |
    var_dump($value); // Shows 1, then 2                          |
}                                                              // |
                                                               // |
function generateOuterYieldFrom(): Generator {                 // |
    // First yield values generated by generateIntegers1And2()    |
    yield from generateIntegers1And2();                        // *<---+
    // then yield integers 3                                           |
    yield 3;                                                     // <--+
    // and 4                                                           |
    yield 4;                                                     //  <-+
}                                                                //    |
                                                                 //    |
foreach (generateOuterYieldFrom() as $value) {                   //    |
    var_dump($value); // Shows 1, 2, 3 and 4                         ->*
}

function generateIntegers56AndReturn(): Generator {
    yield 5;                                                  // <---+
    yield 6;                                                  //  <--+
                                                              //     |
    return ["five", "six"];                       // <--+            |
}                                                 //    |            |
                                                  //    |            |
$gen = generateIntegers56AndReturn();             //    |            |
                                                  //    |            |
// Consume the values **yielded** by                    |            |
// generateIntegers56AndReturn()                        |            |
foreach ($gen as $value) {                        //    |            |
    var_dump($value); // Shows 5, then 6                |          ->*
}                                                 //    |
                                                  //    |
// Access the value **returned** by the generator       |
var_dump($gen->getReturn());                      //  ->*

function wtf(): Generator {
    return ["W", "T", "F", "!"];
    // Without the following line, PHP would complain with a TypeError:
    // Return value of wtf() must be an instance of Generator, array returned.
    // The presence of a yield keyword anywhere inside the function makes it a Generator.
    // However, since we return *before* reaching any *yield*, 42 is never yielded.
    // This is empty generator!
    yield 42;
}

$gen = wtf();

// This foreach loop is not entered!
foreach ($gen as $value) {
    var_dump($value);
}

// However, we can loop on the array *returned* by wtf():
foreach ($gen->getReturn() as $value) {
    echo $value; // Will print: WTF!
}

1
Son örnekte, dönüş fonksiyonun yürütülmesini "sonlandırır", yani kod yeld'e ulaşmaz.
Rodrigo Jarouche

5

Gönderen belgeler :

İçeren herhangi bir işlev yieldbir jeneratör işlevidir.

Bu nedenle yield, yürütülüp yürütülmediği önemli değildir , ayrıştırıcı onu işlev tanımında bir yerde görür ve bir jeneratöre dönüştürür.

İşlev hiçbir zaman yieldifadeyi yürütmezse , jeneratör herhangi bir değer üretmez. returnSonucu kullanmaya çalıştığınızda, döndürülen değer yok sayılır. Belgeler diyor ki:

Not:
PHP 5'te, bir jeneratör bir değer döndüremedi: bunu yapmak derleme hatasına neden olacaktır. Boş bir returnifade, bir jeneratör içindeki geçerli sözdizimiydi ve jeneratörü sonlandıracaktır. PHP 7.0'dan beri, bir jeneratör Generator :: getReturn () kullanılarak alınabilen değerleri döndürebilir .

Böylece şunları yapabilirsiniz:

$gen = generate();
foreach ($gen as $value) {
    echo $value;
}
print_r($gen->getReturn());
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.