@@ -759,6 +759,54 @@ where
759759}
760760
761761impl < ' a , K , V , L : Location < ' a > > KeyedSingleton < K , V , Tick < L > , Bounded > {
762+ /// Creates a [`KeyedStream`] with the same set of keys as `self`, but with the `other` stream
763+ /// used as the values for *each* key.
764+ ///
765+ /// This is helpful when "broadcasting" a set of values so that all the keys have the same
766+ /// values. For example, it can be used to send the same set of elements to several cluster
767+ /// members, if the membership information is available as a [`KeyedSingleton`].
768+ ///
769+ /// # Example
770+ /// ```rust
771+ /// # use hydro_lang::prelude::*;
772+ /// # use futures::StreamExt;
773+ /// # tokio_test::block_on(hydro_lang::test_util::stream_transform_test(|process| {
774+ /// # let tick = process.tick();
775+ /// let keyed_singleton = // { 1: (), 2: () }
776+ /// # process
777+ /// # .source_iter(q!(vec![(1, ()), (2, ())]))
778+ /// # .into_keyed()
779+ /// # .batch(&tick, nondet!(/** test */))
780+ /// # .first();
781+ /// let stream = // [ "a", "b" ]
782+ /// # process
783+ /// # .source_iter(q!(vec!["a".to_string(), "b".to_string()]))
784+ /// # .batch(&tick, nondet!(/** test */));
785+ /// keyed_singleton.flat_map_identical(stream)
786+ /// # .entries().all_ticks()
787+ /// # }, |mut stream| async move {
788+ /// // { 1: ["a", "b" ], 2: ["a", "b"] }
789+ /// # let mut results = Vec::new();
790+ /// # for _ in 0..4 {
791+ /// # results.push(stream.next().await.unwrap());
792+ /// # }
793+ /// # results.sort();
794+ /// # assert_eq!(results, vec![(1, "a".to_string()), (1, "b".to_string()), (2, "a".to_string()), (2, "b".to_string())]);
795+ /// # }));
796+ /// ```
797+ pub fn flat_map_identical < T2 , O2 : Ordering , R : Retries > (
798+ self ,
799+ other : Stream < T2 , Tick < L > , Bounded , O2 , R > ,
800+ ) -> KeyedStream < K , T2 , Tick < L > , Bounded , O2 , R >
801+ where
802+ K : Clone ,
803+ T2 : Clone ,
804+ {
805+ self . keys ( ) . weaken_retries ( ) . cross_product_nested_loop ( other) . into_keyed ( ) . assume_ordering (
806+ nondet ! ( /** keyed stream does not depend on ordering of keys, cross_product_nested_loop preserves order of values */ )
807+ )
808+ }
809+
762810 /// Asynchronously yields this keyed singleton outside the tick, which will
763811 /// be asynchronously updated with the latest set of entries inside the tick.
764812 ///
0 commit comments