Fan-out/Fan-in

Distribute work to N workers and collect all results in one place. A scatter-gather pattern used in parallel processing, map-reduce, and load distribution.

Hew

Workers hold a typed reference to the collector actor. No channels, no WaitGroup, no mutex. Workers call collector.report() — method-call syntax with message-passing semantics underneath.

fan_out.hew
actor Collector {
    let total: Int;
    receive fn report(value: Int) {
        total += value;
    }
    receive fn get_total() -> Int {
        total
    }
}
actor Worker {
    let collector: Collector;
    receive fn compute(n: Int) {
        collector.report(n * n);
    }
}
fn main() {
    let collector = spawn Collector(total: 0);
    let w1 = spawn Worker(collector: collector);
    let w2 = spawn Worker(collector: collector);
    w1.compute(3);
    w2.compute(4);
    sleep_ms(300);
    let total = await collector.get_total();
    println(f"total: {total}");
}

Go

Go uses two channels (jobs and results) with goroutines. You must close the jobs channel when done or workers block forever. You must read exactly the right number of results or goroutines leak.

fan_out.go
func worker(id int, jobs <-chan int, results chan<- int) {
    for n := range jobs {
        results <- n * n
    }
}

func main() {
    jobs := make(chan int, 10)
    results := make(chan int, 10)

    // Start workers
    for i := 0; i < 2; i++ {
        go worker(i, jobs, results)
    }

    // Send work
    jobs <- 3
    jobs <- 4
    close(jobs) // Forget this = deadlock

    // Collect results
    total := 0
    for i := 0; i < 2; i++ {
        total += <-results // Wrong count = goroutine leak
    }
    fmt.Printf("total: %d\n", total)
}

What this shows

Developer experience

Hew's actor-reference pattern eliminates channel lifecycle management. Workers don't know about channels — they call methods on their collector. The topology is expressed through actor fields, not channel wiring.

Debugging

Go's primary failure mode is deadlock: forgot to close a channel, or read the wrong number of results. These are silent until the program hangs. Hew's failure mode is incorrect results from message ordering — which shows up in output, not in a frozen process.

Trade-offs

Go's channel pattern is more flexible for dynamic topologies where the number of workers changes at runtime. Channels can be passed around, combined, and multiplexed. Hew's actor-reference pattern is more rigid (the topology is fixed at spawn time) but eliminates an entire category of lifecycle bugs.