Fibers & Lazy Evaluation
A Fiber is a block of code you can pause with Fiber.yield and resume with resume , cooperatively passing control and values back and forth between the fiber and its caller.
Learn Fibers & Lazy Evaluation in our free Ruby course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Ruby course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll use fibers to build lazy, on-demand sequences and see how Ruby's Enumerator is powered by them.
What You'll Learn in This Lesson
1️⃣ Pause and Resume with Fibers
Create a fiber with Fiber.new {' '} . Calling resume runs it until it hits Fiber.yield , which pauses it and returns a value to the caller. The next resume picks up right after that yield — local variables and all.
2️⃣ Two-Way Communication
Fibers are coroutines: Fiber.yield x sends x out to the caller, and resume(y) sends y back in, becoming the return value of that yield . The first resume usually just primes the fiber up to its first pause.
3️⃣ Lazy Sequences & the Enumerator Connection
Because a fiber produces one value per resume , it's a natural generator: you can model an infinite stream and only compute as far as you pull. Ruby's Enumerator is built on this exact mechanism — enum.next resumes an internal fiber to produce the next item.
🎯 Your Turn
The fiber should pause after each color. Replace each ___ with the call that pauses the fiber and hands a value to the caller.
Build a fiber-based ID generator that yields zero-padded IDs on demand, and run two independent generators side by side. Run with ruby ids.rb .
📋 Quick Reference — Fibers
Practice quiz
How do you create a Fiber?
- Fiber.start { ... }
- Fiber.run { ... }
- Fiber.new { ... }
- fiber { ... }
Answer: Fiber.new { ... }. You create a fiber with Fiber.new { ... } and run it with resume.
What pauses a fiber from inside its block?
- Fiber.yield
- yield
- Fiber.pause
- return
Answer: Fiber.yield. Fiber.yield pauses the fiber and hands control (and a value) back to the caller.
What method continues a paused fiber?
- fiber.next
- fiber.call
- fiber.yield
- fiber.resume
Answer: fiber.resume. fiber.resume continues from where the fiber last paused.
How is a fiber different from a thread?
- Fibers run in parallel
- Fibers are cooperative — they only advance when resumed, with no preemption
- Threads can't share data
- Fibers are preemptive
Answer: Fibers are cooperative — they only advance when resumed, with no preemption. A fiber only runs between resume and the next yield; it is cooperative, so there is no preemption or race conditions.
What happens if you resume a fiber that has already finished?
- It raises FiberError (dead/terminated fiber)
- It returns nil
- It restarts from the top
- It blocks forever
Answer: It raises FiberError (dead/terminated fiber). Resuming a finished fiber raises FiberError about a dead/terminated fiber.
How does a value get INTO a fiber?
- Through Fiber.yield's argument
- Via a global variable
- As the return value of Fiber.yield, via resume(arg)
- You can't pass values in
Answer: As the return value of Fiber.yield, via resume(arg). resume(arg) sends arg in; it becomes the return value of the Fiber.yield that paused the fiber.
Which Ruby class is built on top of fibers internally?
- Array
- Enumerator
- Hash
- Proc
Answer: Enumerator. Enumerator uses a fiber internally; enum.next resumes it to produce the next value.
Why does the first resume of a two-way fiber often just 'prime' it?
- To allocate memory
- To check for errors
- To start a thread
- To run it up to its first yield before you feed values in
Answer: To run it up to its first yield before you feed values in. The first resume runs the fiber to its first pause; later resumes can then send values in.
Can fibers achieve true parallelism on their own?
- Yes, always
- No — only one fiber runs at a time
- Only on multiple cores
- Only with a mutex
Answer: No — only one fiber runs at a time. Fibers are cooperative and run one at a time; for parallelism you reach for threads.
Inside a Fiber block, using the plain keyword instead of will...
- Pause the fiber correctly
- Raise immediately
- Fail to pause the fiber (it's the block keyword, not the fiber pause)
- Resume the caller
Answer: Fail to pause the fiber (it's the block keyword, not the fiber pause). Plain yield calls the block; you must use Fiber.yield to actually pause the fiber.