Skip to content

v0.2.0

Choose a tag to compare

@romac romac released this 08 Mar 17:44
· 165 commits to main since this release
v0.2.0
6b4739f

Added

  • Program type — 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 closure
    • Program::new_send(f) — creates a Send-able program (for use with tokio::spawn)
    • Program::from_co(co) — wraps an existing Co/CoSend coroutine
    • .handle(handler) — attaches the next handler (in effect declaration order); type-checked at compile time
    • .run_sync() — executes synchronously, returns Result<R, Cancelled>
    • .run_sync_stateful(&mut state) — executes synchronously with shared mutable state
    • .run() — executes asynchronously, returns Result<R, Cancelled>
    • .run_stateful(&mut state) — executes asynchronously with shared mutable state
  • handle free 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