ExamplesBy LevelBy TopicLearning Paths
194 Advanced

Coroutines and Generators

Functional Programming

Tutorial Video

Text description (accessibility)

This video demonstrates the "Coroutines and Generators" functional Rust example. Difficulty level: Advanced. Key concepts covered: Functional Programming. Generators and coroutines produce sequences of values lazily — yielding one value at a time rather than computing the entire sequence upfront. Key difference from OCaml: 1. **Native support**: Rust nightly has `Generator` with `yield`; OCaml 5 uses effects for generators; both stable

Tutorial

The Problem

Generators and coroutines produce sequences of values lazily — yielding one value at a time rather than computing the entire sequence upfront. This enables infinite sequences, pipeline processing without intermediate allocations, and cooperative multitasking. Python's yield, JavaScript's function*, C#'s yield return, and Rust's nightly Generator trait all implement this pattern. Understanding generators builds intuition for async/await (generators that yield futures).

🎯 Learning Outcomes

  • • Understand coroutines as functions that can suspend at yield points and be resumed
  • • Learn how to simulate generators in stable Rust using iterators and closures
  • • See the connection between generators and async/await (both are coroutines)
  • • Understand lazy evaluation and infinite sequences through the generator lens
  • Code Example

    #![allow(clippy::all)]
    // Stub — awaiting conversion from OCaml source.

    Key Differences

  • Native support: Rust nightly has Generator with yield; OCaml 5 uses effects for generators; both stable-Rust and pre-5 OCaml use iterators/Seq as approximations.
  • Push vs. pull: Rust iterators are pull-based (caller calls next); OCaml's Seq is pull-based too; push-based generators (callbacks) are also possible.
  • Infinite sequences: Both support infinite lazy sequences; Rust's Iterator chain with take(n) limits consumption; OCaml's Seq.take does the same.
  • **async connection**: Rust's async fn desugars to a state machine similar to generators; yield and await have the same fundamental semantics.
  • OCaml Approach

    OCaml 5's effect handlers implement generators:

    effect Yield : 'a -> unit
    let generate f =
      let next = ref (fun () -> None) in
      (* install an effect handler that captures the continuation *)
      ...
    

    OCaml's Seq module provides lazy sequences equivalent to generators: type 'a node = Nil | Cons of 'a * 'a t where 'a t = unit -> 'a node. Each Cons holds a thunk for the next element — a pull-based generator.

    Full Source

    #![allow(clippy::all)]
    // Stub — awaiting conversion from OCaml source.

    Deep Comparison

    OCaml vs Rust: Coroutines Gen

    Overview

    See the example.rs and example.ml files for detailed implementations.

    Key Differences

    AspectOCamlRust
    Type systemHindley-MilnerOwnership + traits
    MemoryGCZero-cost abstractions
    MutabilityExplicit refmut keyword
    Error handlingOption/ResultResult<T, E>

    See README.md for detailed comparison.

    Exercises

  • Implement an infinite Fibonacci generator as impl Iterator<Item = u64>.
  • Write a take_while generator that yields values from another generator until a predicate fails.
  • Implement a zip_generators combinator that pairs elements from two generators, stopping when either is exhausted.
  • Open Source Repos