id_effect 0.2.0

Effect<A, E, R> (sync + async), context/layers, pipe — interpreter-style, no bundled executor
Documentation
//! Ex 092 — `scoped` vs `scope_with`.
//!
//! - [`id_effect::scoped`] wraps an already-built [`Effect`]: a fresh [`Scope`] is created, the inner
//!   effect runs, then the scope is closed (success → [`Exit::succeed`], error → [`Exit::die`]).
//!   You do **not** get a [`Scope`] handle, so you cannot call [`Scope::add_finalizer`].
//! - [`id_effect::scope_with`] passes a [`Scope`] into your closure so you can register finalizers
//!   (LIFO on close). See `091_scope_with.rs`.
//!
//! Use `scoped` when you only need the uniform exit path around a subgraph. Use `scope_with` when
//! you need explicit finalizers.
use id_effect::{Exit, Never, run_blocking, scope_with, scoped, succeed};
use std::sync::{Arc, Mutex};

fn main() {
  let v = run_blocking(scoped(succeed::<i32, &'static str, ()>(99)), ()).expect("scoped succeed");
  assert_eq!(v, 99);

  let order = Arc::new(Mutex::new(Vec::new()));
  let o = Arc::clone(&order);
  let with_finalizer = scope_with(move |scope| {
    let o1 = Arc::clone(&o);
    scope.add_finalizer(Box::new(move |_e: Exit<(), Never>| {
      o1.lock().unwrap().push(1_u8);
      succeed::<(), Never, ()>(())
    }));
    succeed::<u8, &'static str, ()>(0)
  });
  assert_eq!(run_blocking(with_finalizer, ()), Ok(0));
  assert_eq!(*order.lock().unwrap(), vec![1_u8]);

  println!("092_scoped ok");
}