diff --git a/hydroflow_lang/src/graph/ops/multiset_delta.rs b/hydroflow_lang/src/graph/ops/multiset_delta.rs index eb352ebece98..2f38926c5b06 100644 --- a/hydroflow_lang/src/graph/ops/multiset_delta.rs +++ b/hydroflow_lang/src/graph/ops/multiset_delta.rs @@ -5,30 +5,43 @@ use super::{ WriteContextArgs, RANGE_0, RANGE_1, }; -// TODO(mingwei): more doc -/// Multiset delta from the previous tick. +/// The multiset inverse of [`persist()`](#persist). +/// +/// > 1 input stream of `T`, 1 output stream of `T`, where `T: Eq + Hash` +/// +/// For set semantics, [`unique()`](#unique) can be thought of as a "delta" operator, the inverse +/// of [`persist()`](#persist). In `persist`, new items come in, and all items are repeatedly +/// released out. Conversely, `unique` take repeated items in, and only releases the new ones out. +/// +/// This operator does a similar inversion but for multiset semantics, with some caveats. When it +/// receives duplicate items, instead of ignoring them, it "subtracts" them from the items received +/// in the previous tick, and only releases new items if there are more than in the previous tick. +/// However unlike `unique`, this count is only maintained for the previous tick, not over all time. +/// +/// In the example below, in the second tick two 'a's are removed because two 'a's were received in +/// the previous tick. The third 'a' is released though. /// /// ```rustbook -/// let (input_send, input_recv) = hydroflow::util::unbounded_channel::(); +/// let (input_send, input_recv) = hydroflow::util::unbounded_channel::(); /// let mut flow = hydroflow::hydroflow_syntax! { /// source_stream(input_recv) /// -> multiset_delta() /// -> for_each(|n| println!("{}", n)); /// }; /// -/// input_send.send(3).unwrap(); -/// input_send.send(4).unwrap(); -/// input_send.send(3).unwrap(); +/// input_send.send('a').unwrap(); +/// input_send.send('b').unwrap(); +/// input_send.send('a').unwrap(); /// flow.run_tick(); -/// // 3, 4, 3 +/// // 'a', 'b', 'a' /// -/// input_send.send(3).unwrap(); -/// input_send.send(5).unwrap(); -/// input_send.send(3).unwrap(); -/// input_send.send(3).unwrap(); +/// input_send.send('a').unwrap(); +/// input_send.send('c').unwrap(); +/// input_send.send('a').unwrap(); +/// input_send.send('a').unwrap(); /// flow.run_tick(); -/// // 5, 3 -/// // First two "3"s are removed due to previous tick. +/// // 'c', 'a' +/// // First two 'a's are removed due to previous tick. /// ``` pub const MULTISET_DELTA: OperatorConstraints = OperatorConstraints { name: "multiset_delta", diff --git a/hydroflow_lang/src/graph/ops/persist.rs b/hydroflow_lang/src/graph/ops/persist.rs index 7a29f00446c4..cdeb6f459c1c 100644 --- a/hydroflow_lang/src/graph/ops/persist.rs +++ b/hydroflow_lang/src/graph/ops/persist.rs @@ -5,7 +5,9 @@ use super::{ WriteContextArgs, RANGE_0, RANGE_1, }; -/// Stores each item as it passes through, and replays all item every tick. +/// Stores each item as it passes through, and replays all items every tick. +/// +/// > 1 input stream, 1 output stream /// /// ```hydroflow /// // Normally `source_iter(...)` only emits once, but `persist()` will replay the `"hello"`