Bird
Raised Fist0
PHPprogramming~15 mins

Yield from delegation in PHP - Deep Dive

Choose your learning style10 modes available
Overview - Yield from delegation
What is it?
Yield from delegation is a way in PHP to let one generator hand over part of its work to another generator. This means a generator can pause and let another generator produce values, then continue after that. It helps write cleaner and simpler code when dealing with sequences of values from multiple sources.
Why it matters
Without yield from delegation, you would have to manually loop through each generator and yield values one by one, which can be repetitive and error-prone. Yield from delegation makes code easier to read and maintain, especially when combining multiple data streams or breaking complex tasks into smaller parts.
Where it fits
Before learning yield from delegation, you should understand basic generators and how yield works in PHP. After mastering yield from delegation, you can explore advanced generator features like sending values into generators or using generators for asynchronous programming.
Mental Model
Core Idea
Yield from delegation lets one generator pass control and values to another generator seamlessly, like handing off a baton in a relay race.
Think of it like...
Imagine a relay race where one runner passes the baton to the next runner who runs their part of the race before passing it back. Yield from delegation is like that baton pass between generators, letting each do their part in order.
Main Generator
  │
  ├─ yields some values
  │
  ├─ ──▶ Delegated Generator (via yield from)
  │       │
  │       ├─ yields multiple values
  │       └─ returns a final value
  │
  └─ resumes after delegation
Build-Up - 6 Steps
1
FoundationUnderstanding basic generators
🤔
Concept: Learn what generators are and how yield produces values one at a time.
Result
1 2 3
Understanding how yield pauses and resumes function execution is key to grasping how generators work.
2
FoundationManually yielding from another generator
🤔
Concept: See how to yield values from one generator inside another by looping.
Result
1 2 3
Manually looping to yield values works but can be verbose and repetitive.
3
IntermediateUsing yield from for delegation
🤔Before reading on: do you think yield from replaces manual loops or just simplifies them? Commit to your answer.
Concept: Learn how yield from lets one generator delegate yielding to another generator directly.
Result
1 2 3
Yield from delegation removes boilerplate loops, making code cleaner and easier to read.
4
IntermediateCapturing return values from delegated generators
🤔Before reading on: do you think yield from can capture a generator's return value? Commit to yes or no.
Concept: Discover that yield from not only yields values but also returns the delegated generator's return value.
Result
Returned: 42 1 2 3
Knowing yield from returns the delegated generator's return value allows combining results and controlling flow.
5
AdvancedDelegation with nested generators
🤔Before reading on: do you think yield from works recursively with multiple nested generators? Commit to yes or no.
Concept: Explore how yield from can delegate through multiple layers of generators seamlessly.
Result
1 10 20 30 2
Understanding recursive delegation helps manage complex sequences with layered generators.
6
ExpertInternal mechanics of yield from delegation
🤔Before reading on: do you think yield from creates a new generator context or just forwards calls? Commit to your answer.
Concept: Learn how yield from forwards calls and values between generators without creating new contexts, preserving state and exceptions.
Internally, yield from forwards the current generator's execution to the delegated generator. It passes yielded values, exceptions, and return values transparently. This means the outer generator pauses, the inner generator runs until completion, then control returns with results. This forwarding avoids manual loops and preserves generator state.
Result
Yield from acts like a transparent bridge between generators, forwarding all interactions.
Knowing the forwarding mechanism explains why yield from is more efficient and less error-prone than manual loops.
Under the Hood
Yield from delegation works by forwarding the generator's execution context to the delegated generator. When yield from is called, the outer generator pauses, and the inner generator runs until it yields all its values or returns. All yielded values, exceptions, and return values are passed through transparently. This forwarding means the outer generator does not need to manually loop or handle the inner generator's state.
Why designed this way?
PHP introduced yield from to simplify generator composition and delegation. Before, developers had to write manual loops to yield values from nested generators, which was verbose and error-prone. The design choice to forward calls and values transparently keeps generator state intact and allows capturing return values, making generator code cleaner and more powerful.
Outer Generator
  │
  │ calls yield from
  ▼
┌───────────────────┐
│ Delegated Generator│
│ yields values      │
│ returns final val  │
└───────────────────┘
  ▲
  │ forwards yields and return
  │
Outer Generator resumes
Myth Busters - 4 Common Misconceptions
Quick: Does yield from create a new generator instance each time it is called? Commit to yes or no.
Common Belief:Yield from creates a new generator instance every time it is called, so it duplicates generators.
Tap to reveal reality
Reality:Yield from delegates to an existing generator instance and forwards calls; it does not create new instances automatically.
Why it matters:Believing it creates new instances can lead to confusion about generator state and unexpected behavior in loops or recursion.
Quick: Can yield from only be used with generators? Commit to yes or no.
Common Belief:Yield from only works with generators and cannot delegate to other iterables.
Tap to reveal reality
Reality:In PHP, yield from can delegate to any iterable, including arrays and objects implementing Traversable.
Why it matters:Limiting yield from to generators reduces its usefulness and leads to unnecessary manual loops over arrays or iterables.
Quick: Does yield from automatically catch exceptions from delegated generators? Commit to yes or no.
Common Belief:Yield from catches all exceptions from the delegated generator and handles them silently.
Tap to reveal reality
Reality:Yield from forwards exceptions from the delegated generator to the outer generator; it does not catch or suppress them.
Why it matters:Misunderstanding exception forwarding can cause bugs where exceptions are unexpectedly unhandled or swallowed.
Quick: Does yield from return the last yielded value from the delegated generator? Commit to yes or no.
Common Belief:Yield from returns the last value yielded by the delegated generator.
Tap to reveal reality
Reality:Yield from returns the value returned by the delegated generator via a return statement, not the last yielded value.
Why it matters:Confusing yield and return values can cause logic errors when combining generator results.
Expert Zone
1
Yield from preserves generator keys, so keys yielded by the delegated generator appear unchanged in the outer generator.
2
When multiple yield from statements are stacked, exceptions propagate through all layers unless caught explicitly, which can affect error handling.
3
Using yield from with generators that accept sent values (via send()) requires careful forwarding of sent values to maintain correct behavior.
When NOT to use
Yield from is not suitable when you need to process or transform each yielded value individually before passing it on. In such cases, manual loops with yield are better. Also, for very simple sequences, yield from may add unnecessary complexity.
Production Patterns
In real-world PHP applications, yield from delegation is used to compose complex data streams, such as reading multiple files line-by-line, combining API paginated results, or building pipelines for data processing. It helps keep code modular and efficient.
Connections
Coroutines in Python
Both use yield/yield from to delegate execution and pass values between functions.
Understanding yield from in PHP helps grasp Python's coroutine delegation, showing a shared pattern in asynchronous and generator-based programming.
Event delegation in web development
Both delegate responsibility from one handler to another to simplify control flow.
Recognizing delegation patterns across domains reveals how passing control improves modularity and reduces code duplication.
Assembly language subroutine calls
Yield from delegation is like a subroutine call that pauses the caller until the callee finishes.
Seeing yield from as a controlled pause and resume mechanism connects high-level generators to low-level call stack management.
Common Pitfalls
#1Trying to yield from a non-iterable value.
Wrong approach:
Correct approach:
Root cause:Yield from expects an iterable; passing a non-iterable causes a runtime error.
#2Expecting yield from to transform values automatically.
Wrong approach:
Correct approach:
Root cause:Yield from only delegates yielding; it does not modify values. Transformation requires explicit code.
#3Ignoring the return value of yield from when needed.
Wrong approach:
Correct approach:
Root cause:Not capturing the return value loses important information from delegated generators.
Key Takeaways
Yield from delegation lets one generator pass control and values to another generator cleanly and efficiently.
It simplifies code by removing manual loops needed to yield values from nested generators or iterables.
Yield from also captures the return value of the delegated generator, enabling richer control flow.
Understanding how yield from forwards execution and exceptions clarifies its power and limitations.
Using yield from properly improves modularity and readability in complex data processing tasks.

Practice

(1/5)
1.

What does the yield from statement do in PHP generators?

easy
A. It delegates yielding values from another generator or iterable.
B. It stops the generator immediately.
C. It converts a generator into an array.
D. It throws an exception inside the generator.

Solution

  1. Step 1: Understand the purpose of yield from

    yield from is used to delegate yielding values from another generator or iterable, so you don't have to write a loop to yield each value manually.
  2. Step 2: Compare with other options

    Stopping a generator, converting it to an array, or throwing exceptions are unrelated to yield from.
  3. Final Answer:

    It delegates yielding values from another generator or iterable. -> Option A
  4. Quick Check:

    yield from delegates values [OK]
Hint: Remember: yield from passes values from another generator [OK]
Common Mistakes:
  • Thinking yield from stops the generator
  • Confusing yield from with array conversion
  • Assuming it throws exceptions
2.

Which of the following is the correct syntax to delegate yielding from another generator $gen inside a generator function?

function gen() {
    // your code here
}
easy
A. yield $gen;
B. yield to $gen;
C. yield($gen);
D. yield from $gen;

Solution

  1. Step 1: Recall correct yield from syntax

    The correct syntax to delegate yielding from another generator is yield from $gen;.
  2. Step 2: Check other options for syntax errors

    yield $gen; yields the generator object itself, not its values. yield($gen); is invalid syntax. yield to $gen; is not valid PHP syntax.
  3. Final Answer:

    yield from $gen; -> Option D
  4. Quick Check:

    Correct syntax uses yield from [OK]
Hint: Use exact phrase yield from to delegate generators [OK]
Common Mistakes:
  • Using just yield $gen; instead of yield from
  • Adding parentheses incorrectly
  • Writing invalid keywords like 'yield to'
3.

What will be the output of the following PHP code?

function gen1() {
    yield 1;
    yield 2;
}

function gen2() {
    yield from gen1();
    yield 3;
}

foreach (gen2() as $value) {
    echo $value . ' ';
}
medium
A. 1 3 2
B. 3 1 2
C. 1 2 3
D. 1 2

Solution

  1. Step 1: Understand yield from gen1() in gen2()

    This delegates yielding values 1 and 2 from gen1() inside gen2().
  2. Step 2: Trace the output of the foreach loop

    The loop yields 1, then 2 from gen1(), then yields 3 from gen2(). So output is "1 2 3 "
  3. Final Answer:

    1 2 3 -> Option C
  4. Quick Check:

    Delegation yields 1,2 then 3 [OK]
Hint: Remember yield from outputs all delegated values first [OK]
Common Mistakes:
  • Assuming order is changed
  • Forgetting the last yield after delegation
  • Thinking yield from yields the generator object
4.

Identify the error in this PHP generator code:

function genA() {
    yield 1;
    yield 2;
}

function genB() {
    yield genA();
    yield 3;
}

foreach (genB() as $val) {
    echo $val . ' ';
}
medium
A. It yields the generator object instead of its values.
B. Missing semicolon after yield statements.
C. Cannot yield inside a function.
D. The foreach loop is invalid syntax.

Solution

  1. Step 1: Analyze yield genA(); in genB()

    This yields the generator object genA() itself, not the values it produces.
  2. Step 2: Understand correct delegation with yield from

    To yield values from genA(), use yield from genA(); instead of yield genA();.
  3. Final Answer:

    It yields the generator object instead of its values. -> Option A
  4. Quick Check:

    Use yield from to delegate values [OK]
Hint: Use yield from to yield values, not the generator object [OK]
Common Mistakes:
  • Using yield instead of yield from for delegation
  • Assuming yielding a generator yields its values
  • Ignoring the need to delegate properly
5.

Given two generators genX() yielding numbers 1 to 3 and genY() yielding numbers 4 to 6, how can you create a generator genZ() that yields all numbers from 1 to 6 using yield from?

function genX() {
    yield 1;
    yield 2;
    yield 3;
}

function genY() {
    yield 4;
    yield 5;
    yield 6;
}

function genZ() {
    // Fill in code here
}
hard
A. yield genX(); yield genY();
B. yield from genX(); yield from genY();
C. yield genX() + genY();
D. yield from genY(); yield from genX();

Solution

  1. Step 1: Use yield from to delegate both generators in order

    To yield all numbers from 1 to 6 in sequence, delegate genX() first, then genY() using yield from.
  2. Step 2: Check order and syntax

    yield from genX(); yield from genY(); yields 1,2,3 then 4,5,6. yield from genY(); yield from genX(); reverses order. Options B and C yield generator objects or invalid expressions.
  3. Final Answer:

    yield from genX(); yield from genY(); -> Option B
  4. Quick Check:

    Delegate generators in order with yield from [OK]
Hint: Chain generators with multiple yield from statements [OK]
Common Mistakes:
  • Yielding generators instead of delegating
  • Reversing the order of delegation
  • Trying to add generators directly
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard