Strategy

Trait Strategy 

Source
pub trait Strategy:
    Clone
    + Send
    + Sync
    + Debug
    + 'static {
    // Required method
    fn fold_init<I, INIT, T, R, ID, F, RD>(
        &self,
        iter: I,
        init: INIT,
        identity: ID,
        fold_op: F,
        reduce_op: RD,
    ) -> R
       where I: IntoIterator<IntoIter: Send, Item: Send> + Send,
             INIT: Fn() -> T + Send + Sync,
             T: Send,
             R: Send,
             ID: Fn() -> R + Send + Sync,
             F: Fn(R, &mut T, I::Item) -> R + Send + Sync,
             RD: Fn(R, R) -> R + Send + Sync;

    // Provided methods
    fn fold<I, R, ID, F, RD>(
        &self,
        iter: I,
        identity: ID,
        fold_op: F,
        reduce_op: RD,
    ) -> R
       where I: IntoIterator<IntoIter: Send, Item: Send> + Send,
             R: Send,
             ID: Fn() -> R + Send + Sync,
             F: Fn(R, I::Item) -> R + Send + Sync,
             RD: Fn(R, R) -> R + Send + Sync { ... }
    fn map_collect_vec<I, F, T>(&self, iter: I, map_op: F) -> Vec<T>
       where I: IntoIterator<IntoIter: Send, Item: Send> + Send,
             F: Fn(I::Item) -> T + Send + Sync,
             T: Send { ... }
    fn map_init_collect_vec<I, INIT, T, F, R>(
        &self,
        iter: I,
        init: INIT,
        map_op: F,
    ) -> Vec<R>
       where I: IntoIterator<IntoIter: Send, Item: Send> + Send,
             INIT: Fn() -> T + Send + Sync,
             T: Send,
             F: Fn(&mut T, I::Item) -> R + Send + Sync,
             R: Send { ... }
}
Expand description

A strategy for executing fold operations.

This trait abstracts over sequential and parallel execution, allowing algorithms to be written generically and then executed with different strategies depending on the use case (e.g., sequential for testing/debugging, parallel for production).

Required Methods§

Source

fn fold_init<I, INIT, T, R, ID, F, RD>( &self, iter: I, init: INIT, identity: ID, fold_op: F, reduce_op: RD, ) -> R
where I: IntoIterator<IntoIter: Send, Item: Send> + Send, INIT: Fn() -> T + Send + Sync, T: Send, R: Send, ID: Fn() -> R + Send + Sync, F: Fn(R, &mut T, I::Item) -> R + Send + Sync, RD: Fn(R, R) -> R + Send + Sync,

Reduces a collection to a single value with per-partition initialization.

Similar to fold, but provides a separate initialization value that is created once per partition. This is useful when the fold operation requires mutable state that should not be shared across partitions (e.g., a scratch buffer, RNG, or expensive-to-clone resource).

§Arguments
  • iter: The collection to fold over
  • init: Creates the per-partition initialization value
  • identity: Creates the identity value for the accumulator
  • fold_op: Combines accumulator with init state and item: (acc, &mut init, item) -> acc
  • reduce_op: Combines two accumulators: (acc1, acc2) -> acc
§Examples
use commonware_parallel::{Strategy, Sequential};

let strategy = Sequential;
let data = vec![1u32, 2, 3, 4, 5];

// Use a scratch buffer to avoid allocations in the inner loop
let result: Vec<String> = strategy.fold_init(
    &data,
    || String::with_capacity(16),  // Per-partition scratch buffer
    Vec::new,                       // Identity for accumulator
    |mut acc, buf, &n| {
        buf.clear();
        use std::fmt::Write;
        write!(buf, "num:{}", n).unwrap();
        acc.push(buf.clone());
        acc
    },
    |mut a, b| { a.extend(b); a },
);

assert_eq!(result, vec!["num:1", "num:2", "num:3", "num:4", "num:5"]);

Provided Methods§

Source

fn fold<I, R, ID, F, RD>( &self, iter: I, identity: ID, fold_op: F, reduce_op: RD, ) -> R
where I: IntoIterator<IntoIter: Send, Item: Send> + Send, R: Send, ID: Fn() -> R + Send + Sync, F: Fn(R, I::Item) -> R + Send + Sync, RD: Fn(R, R) -> R + Send + Sync,

Reduces a collection to a single value using fold and reduce operations.

This method processes elements from the iterator, combining them into a single result.

§Arguments
  • iter: The collection to fold over
  • identity: A closure that produces the identity value for the fold.
  • fold_op: Combines an accumulator with a single item: (acc, item) -> acc
  • reduce_op: Combines two accumulators: (acc1, acc2) -> acc.
§Examples
§Sum of Elements
use commonware_parallel::{Strategy, Sequential};

let strategy = Sequential;
let numbers = vec![1, 2, 3, 4, 5];

let sum = strategy.fold(
    &numbers,
    || 0,                    // identity
    |acc, &n| acc + n,       // fold: add each number
    |a, b| a + b,            // reduce: combine partial sums
);

assert_eq!(sum, 15);
Source

fn map_collect_vec<I, F, T>(&self, iter: I, map_op: F) -> Vec<T>
where I: IntoIterator<IntoIter: Send, Item: Send> + Send, F: Fn(I::Item) -> T + Send + Sync, T: Send,

Maps each element and collects results into a Vec.

This is a convenience method that applies map_op to each element and collects the results. For Sequential, elements are processed in order. For Rayon, elements may be processed out of order but the final vector preserves the original ordering.

§Arguments
  • iter: The collection to map over
  • map_op: The mapping function to apply to each element
§Examples
use commonware_parallel::{Strategy, Sequential};

let strategy = Sequential;
let data = vec![1, 2, 3, 4, 5];

let squared: Vec<i32> = strategy.map_collect_vec(&data, |&x| x * x);
assert_eq!(squared, vec![1, 4, 9, 16, 25]);
Source

fn map_init_collect_vec<I, INIT, T, F, R>( &self, iter: I, init: INIT, map_op: F, ) -> Vec<R>
where I: IntoIterator<IntoIter: Send, Item: Send> + Send, INIT: Fn() -> T + Send + Sync, T: Send, F: Fn(&mut T, I::Item) -> R + Send + Sync, R: Send,

Maps each element with per-partition state and collects results into a Vec.

Combines map_collect_vec with per-partition initialization like fold_init. Useful when the mapping operation requires mutable state that should not be shared across partitions.

§Arguments
  • iter: The collection to map over
  • init: Creates the per-partition initialization value
  • map_op: The mapping function: (&mut init, item) -> result
§Examples
use commonware_parallel::{Strategy, Sequential};

let strategy = Sequential;
let data = vec![1, 2, 3, 4, 5];

// Use a counter that tracks position within each partition
let indexed: Vec<(usize, i32)> = strategy.map_init_collect_vec(
    &data,
    || 0usize, // Per-partition counter
    |counter, &x| {
        let idx = *counter;
        *counter += 1;
        (idx, x * 2)
    },
);

assert_eq!(indexed, vec![(0, 2), (1, 4), (2, 6), (3, 8), (4, 10)]);

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§