v0.2.0
Added
-
Programtype — a builder-style API for assembling and running effect-handled computations. This is now the recommended way to use the library for most users.The key feature is incremental handler attachment: handlers are added one at a time via
.handle(), which means a partially-handled program is a first-class value you can pass around, store, or extend later. The compiler tracks which effects are still unhandled and only permits running the computation once all effects have a handler.// Define a computation once... let program = Program::new(|yielder: Yielder<'_, Effs>| async move { let n = yielder.yield_(Counter).await; let answer = yielder.yield_(Ask("question")).await; (answer, n) }); // ...attach handlers incrementally, e.g. in different modules or call sites... let program = program.handle(|_: Counter| CoControl::resume(42u64)); let program = program.handle(|_: Ask| CoControl::resume("yes")); // ...and run only when all effects are handled. let result = program.run_sync();
Available constructors and methods:
Program::new(f)— creates a program from an async closureProgram::new_send(f)— creates aSend-able program (for use withtokio::spawn)Program::from_co(co)— wraps an existingCo/CoSendcoroutine.handle(handler)— attaches the next handler (in effect declaration order); type-checked at compile time.run_sync()— executes synchronously, returnsResult<R, Cancelled>.run_sync_stateful(&mut state)— executes synchronously with shared mutable state.run()— executes asynchronously, returnsResult<R, Cancelled>.run_stateful(&mut state)— executes asynchronously with shared mutable state
-
handlefree function — functional alternative to.handle(), useful when incrementally building up a program across call sites without method chaining:let p = handle(p, |_: Counter| CoControl::resume(42u64)); let p = handle(p, |_: Ask| CoControl::resume("yes")); p.run_sync()
-
All public items are now documented.
Full Changelog: v0.1.0...v0.2.0