terni 0.4.0

Ternary error handling: Success, Partial with measured loss, Failure. Because computation is not binary.
Documentation
  • Coverage
  • 100%
    45 out of 45 items documented1 out of 42 items with examples
  • Size
  • Source code size: 90.8 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 3.96 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 1m 29s Average build duration of successful builds.
  • all releases: 1m 24s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • systemic-engineering/prism
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • alexocode

terni

I wanna thank Brene Brown for her work.

Ternary error handling for Rust. Because computation is not binary.

crates.io docs.rs license

eh

The type. Three states instead of two.

use terni::{Imperfect, ConvergenceLoss};

let perfect: Imperfect<u32, String, ConvergenceLoss> = Imperfect::Success(42);
let lossy = Imperfect::Partial(42, ConvergenceLoss::new(3));
let failed: Imperfect<u32, String, ConvergenceLoss> = Imperfect::Failure("gone".into(), ConvergenceLoss::new(0));

assert!(perfect.is_ok());
assert!(lossy.is_partial());
assert!(failed.is_err());

Loss measures what didn't survive. It's a monoid: zero() identity, combine associative, total() absorbing.

Three loss types ship with the crate:

  • ConvergenceLoss — distance to crystal. Combine: max.
  • ApertureLoss — dark dimensions. Combine: union.
  • RoutingLoss — decision entropy. Combine: max entropy, min gap.

Loss types in depth →

eh!

The bind. Chain operations, accumulate loss.

use terni::{Imperfect, ConvergenceLoss};

let result = Imperfect::<i32, String, ConvergenceLoss>::Success(1)
    .eh(|x| Imperfect::Success(x * 2))
    .eh(|x| Imperfect::Partial(x + 1, ConvergenceLoss::new(3)));

assert_eq!(result.ok(), Some(3));
assert!(result.is_partial());

For explicit context with loss accumulation:

use terni::{Imperfect, Eh, ConvergenceLoss};

let mut eh = Eh::new();
let a = eh.eh(Imperfect::<i32, String, ConvergenceLoss>::Success(1)).unwrap();
let b = eh.eh(Imperfect::<_, String, _>::Partial(a + 1, ConvergenceLoss::new(5))).unwrap();
let result: Imperfect<i32, String, ConvergenceLoss> = eh.finish(b);

assert!(result.is_partial());

.imp() and .tri() are aliases for .eh() — same bind, different name. Use whichever reads best in your code.

Pipeline guide → · Context guide →

eh?

The question. Coming in a future release.

Block macro for implicit loss accumulation — eh! { } will do what Eh does without the boilerplate.

More

  • Loss types — the Loss trait, shipped types, custom implementations
  • Pipeline.eh() bind in depth, loss accumulation rules
  • ContextEh struct, mixing Imperfect and Result
  • Terni-functor — the math behind .eh()
  • Migration — moving from Result<T, E> to Imperfect<T, E, L>

License

Apache-2.0