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);