Skip to main content

transduce

Function transduce 

Source
pub fn transduce(
    cx: &mut Cx,
    source: &Value,
    pipeline: TransducerPipeline,
    init: Value,
    reducer: Arc<dyn Fn(&mut Cx, Value, Value) -> Result<Value> + Send + Sync + 'static>,
) -> Result<Value>
Expand description

Stream source through pipeline and fold survivors into a single value.

The one-pass core combining transformation and reduction: each element is run through pipeline, and surviving elements are folded with reducer from init.

ยงExamples

use std::sync::Arc;
use sim_kernel::{Cx, DefaultFactory, Expr, NoopEvalPolicy, NumberLiteral, Symbol, Value};
use sim_lib_sequence::{lazy_sequence_value, transduce, TransducerPipeline};

fn n(cx: &mut Cx, v: u64) -> Value {
    cx.factory().number_literal(Symbol::qualified("test", "u64"), v.to_string()).unwrap()
}
fn read(cx: &mut Cx, v: &Value) -> u64 {
    let Expr::Number(NumberLiteral { canonical, .. }) = v.object().as_expr(cx).unwrap() else {
        panic!("number");
    };
    canonical.parse().unwrap()
}

let mut cx = Cx::new(Arc::new(NoopEvalPolicy), Arc::new(DefaultFactory));
// Source yields 0, 1, 2 then ends.
let source = lazy_sequence_value(&mut cx, Arc::new(|cx: &mut Cx, i| {
    if i >= 3 { return Ok(None); }
    Ok(Some(n(cx, i as u64)))
}))?;

let zero = n(&mut cx, 0);
let sum = transduce(
    &mut cx,
    &source,
    TransducerPipeline::new(),
    zero,
    Arc::new(|cx, acc, value| {
        let total = read(cx, &acc) + read(cx, &value);
        Ok(n(cx, total))
    }),
)?;
assert_eq!(read(&mut cx, &sum), 3);