terminals-core 0.1.0

Core runtime primitives for Terminals OS: phase dynamics, AXON wire protocol, substrate engine, and sematonic types
Documentation
/// McCarthy's amb — sequential backtrack, returns first Ok
pub fn amb<T, E, F>(choices: &[F]) -> Result<T, E>
where
    F: Fn() -> Result<T, E>,
{
    let mut last_err = None;
    for choice in choices {
        match choice() {
            Ok(v) => return Ok(v),
            Err(e) => last_err = Some(e),
        }
    }
    Err(last_err.expect("amb called with empty choices"))
}

/// Explore — run all choices, collect all Ok results
pub fn explore<T, E, F>(choices: &[F]) -> Vec<T>
where
    F: Fn() -> Result<T, E>,
{
    choices.iter().filter_map(|f| f().ok()).collect()
}

/// Explore with combiner — aggregate all Ok results
pub fn explore_with<T, R, E, F, C>(choices: &[F], combiner: C) -> Result<R, E>
where
    T: std::fmt::Debug,
    F: Fn() -> Result<T, E>,
    C: FnOnce(Vec<T>) -> R,
{
    let results = explore(choices);
    if results.is_empty() {
        Err(choices[0]().unwrap_err())
    } else {
        Ok(combiner(results))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_amb_first_success() {
        let choices: Vec<fn() -> Result<i32, &'static str>> =
            vec![|| Err("fail 1"), || Ok(42), || Ok(99)];
        let result = amb(&choices);
        assert_eq!(result, Ok(42));
    }

    #[test]
    fn test_amb_all_fail() {
        let choices: Vec<fn() -> Result<i32, &'static str>> =
            vec![|| Err("fail 1"), || Err("fail 2")];
        let result = amb(&choices);
        assert!(result.is_err());
    }

    #[test]
    fn test_explore_all() {
        let choices: Vec<fn() -> Result<i32, &'static str>> = vec![|| Ok(1), || Ok(2), || Ok(3)];
        let results = explore(&choices);
        assert_eq!(results.len(), 3);
    }
}