Return
Đơn giản chỉ cần trả lại một giá trị duy nhất cho người gọi.
Yield
Chuyển đổi hàm / phương thức hiện tại để trả về a Generator
, sẽ tạo ra nhiều hơn một giá trị duy nhất: mỗi lần yield
được kích hoạt, nó cung cấp giá trị cho người gọi, mỗi lần, theo cách truyền thống sử dụng một foreach
vòng lặp.
Yield
+ Return
Các trình tạo, ngoài việc tạo các giá trị, cũng có thể, cung cấp một giá trị được trả về duy nhất. Giá trị đó sẽ không phải là một phần của vòng lặp xung quanh trình tạo, nó phải được truy cập bằng Generator::getReturn()
phương thức.
Return
+ Yield
Điều này có thể được coi là một lỗi, tuy nhiên, nó không phải là.
Đó là hai giai đoạn:
- Từ mã đến mã byte : trong giai đoạn này,
generate()
hàm được xem là có chứa yield
từ khóa, do đó nó được đánh dấu là tạo ra a Generator
.
- Thực thi : Bởi vì
return
xảy ra trước yield
, máy phát điện không có cơ hội tạo ra bất kỳ giá trị nào. Tuy nhiên, [1, 2, 3]
mảng có thể được lấy với Generator::getReturn()
.
Một ví dụ chú thích đầy đủ:
// 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!
}
var_dump(generate()->GetReturn());