pub trait ParRec: Sized + ParRecCore {
Show 28 methods
// Required methods
fn runner<Q: ParRunner>(
self,
runner: Q,
) -> impl ParRec<Item = Self::Item, Xap = Self::Xap, Input = Self::Input>;
fn runner_with_diagnostics(
self,
) -> impl ParRec<Item = Self::Item, Xap = Self::Xap, Input = Self::Input>;
fn num_threads(self, num_threads: impl Into<NumThreads>) -> Self;
fn chunk_size(self, chunk_size: impl Into<ChunkSize>) -> Self;
fn iteration_order(self, collect: IterationOrder) -> Self;
fn map<Q, H>(
self,
h: H,
) -> impl ParRec<Item = Q, Xap = MapOf<Self::Xap, Q, H>, Input = Self::Input>
where H: Fn(Self::Item) -> Q + Copy + Send;
fn inspect<H>(
self,
h: H,
) -> impl ParRec<Item = Self::Item, Xap = InsOf<Self::Xap, H>, Input = Self::Input>
where H: Fn(&Self::Item) + Copy + Send;
fn filter<H>(
self,
h: H,
) -> impl ParRec<Item = Self::Item, Xap = FilOf<Self::Xap, H>, Input = Self::Input>
where H: Fn(&Self::Item) -> bool + Copy + Send;
fn filter_map<Q, H>(
self,
h: H,
) -> impl ParRec<Item = Q, Xap = FilMapOf<Self::Xap, Q, H>, Input = Self::Input>
where H: Fn(Self::Item) -> Option<Q> + Copy + Send;
fn flat_map<V, H>(
self,
h: H,
) -> impl ParRec<Item = V::Item, Xap = FlatMapOf<Self::Xap, V, H>, Input = Self::Input>
where V: IntoIterator,
H: Fn(Self::Item) -> V + Copy + Send;
fn flatten(
self,
) -> impl ParRec<Item = <Self::Item as IntoIterator>::Item, Xap = FlattenOf<Self::Xap>, Input = Self::Input>
where Self::Item: IntoIterator;
fn first(self) -> Option<Self::Item>
where Self::Item: Send,
<Self::Input as IntoIterator>::Item: Send;
fn reduce<F>(self, f: F) -> Option<Self::Item>
where F: Fn(Self::Item, Self::Item) -> Self::Item + Send + Copy,
Self::Item: Send,
<Self::Input as IntoIterator>::Item: Send;
fn collect_into<P>(self, dst: &mut P)
where P: ParExtend<Self::Item>,
Self::Item: Send,
<Self::Input as IntoIterator>::Item: Send;
fn fold<B, I, F>(self, init: I, f: F) -> Vec<B>
where B: Send,
I: Fn() -> B,
F: Fn(&mut B, Self::Item) + Copy + Send,
<Self::Input as IntoIterator>::Item: Send;
// Provided methods
fn collect<P>(self) -> P
where P: ParExtend<Self::Item> + Default,
Self::Item: Send,
<Self::Input as IntoIterator>::Item: Send { ... }
fn all<F>(self, f: F) -> bool
where F: Fn(&Self::Item) -> bool + Copy + Send,
<Self::Input as IntoIterator>::Item: Send { ... }
fn any<F>(self, f: F) -> bool
where F: Fn(&Self::Item) -> bool + Copy + Send,
<Self::Input as IntoIterator>::Item: Send { ... }
fn count(self) -> usize
where <Self::Input as IntoIterator>::Item: Send { ... }
fn find<F>(self, f: F) -> Option<Self::Item>
where Self::Item: Send,
F: Fn(&Self::Item) -> bool + Copy + Send,
<Self::Input as IntoIterator>::Item: Send { ... }
fn for_each<F>(self, f: F)
where F: Fn(Self::Item) + Send + Copy,
<Self::Input as IntoIterator>::Item: Send { ... }
fn max(self) -> Option<Self::Item>
where Self::Item: Ord + Send,
<Self::Input as IntoIterator>::Item: Send { ... }
fn max_by<F>(self, f: F) -> Option<Self::Item>
where Self::Item: Send,
F: Fn(&Self::Item, &Self::Item) -> Ordering + Copy + Send,
<Self::Input as IntoIterator>::Item: Send { ... }
fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>
where Self::Item: Send,
B: Ord,
F: Fn(&Self::Item) -> B + Copy + Send,
<Self::Input as IntoIterator>::Item: Send { ... }
fn min(self) -> Option<Self::Item>
where Self::Item: Ord + Send,
<Self::Input as IntoIterator>::Item: Send { ... }
fn min_by<F>(self, f: F) -> Option<Self::Item>
where Self::Item: Send,
F: Fn(&Self::Item, &Self::Item) -> Ordering + Copy + Send,
<Self::Input as IntoIterator>::Item: Send { ... }
fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>
where Self::Item: Send,
B: Ord,
F: Fn(&Self::Item) -> B + Copy + Send,
<Self::Input as IntoIterator>::Item: Send { ... }
fn sum<S>(self) -> S
where Self::Item: Sum<S>,
S: Send,
<Self::Input as IntoIterator>::Item: Send { ... }
}Expand description
Infallible parallel recursive iterator.
ParRec is the central trait for describing recursive parallel computations as iterator
pipelines. It mirrors common sequential iterator operations (map,
filter, flat_map, collect, reduce, …) while allowing runtime
configuration of execution details such as number of threads, chunk size,
iteration order, and runner/pool selection.
Recursive traversal can be deterministic: with IterationOrder::Ordered (the default),
order-sensitive operations use breadth-first order, level by level and left-to-right following
input and child generation order.
Related traits:
ParUsefor worker-local mutable state,ParOptionforOption-based fallibility,ParResultforResult-based fallibility.
§Examples
use orx_parallel::*;
// A small rooted tree represented as adjacency lists; node 0 is the root.
let children: Vec<Vec<usize>> = vec![vec![1, 2], vec![3, 4], vec![5], vec![], vec![], vec![]];
let sum_of_even_squares: usize = par_recursive([0usize], |node| children[*node].iter().copied())
.map(|x| x * x)
.filter(|x| x % 2 == 0)
.sum();
assert_eq!(sum_of_even_squares, 20);Required Methods§
Sourcefn runner<Q: ParRunner>(
self,
runner: Q,
) -> impl ParRec<Item = Self::Item, Xap = Self::Xap, Input = Self::Input>
fn runner<Q: ParRunner>( self, runner: Q, ) -> impl ParRec<Item = Self::Item, Xap = Self::Xap, Input = Self::Input>
Replaces the current parallel runner with runner.
This allows per-computation control over execution strategy.
Please see Runner for parallel runners implemented in this crate.
§Examples
use orx_parallel::*;
let children: Vec<Vec<usize>> = vec![vec![1, 2], vec![3, 4], vec![5], vec![], vec![], vec![]];
let baseline: usize = par_recursive([0usize], |node| children[*node].iter().copied()).sum();
let par = par_recursive([0usize], |node| children[*node].iter().copied());
let par = par.runner(Runner::fixed());
let configured: usize = par.sum();
assert_eq!(baseline, configured);Sourcefn runner_with_diagnostics(
self,
) -> impl ParRec<Item = Self::Item, Xap = Self::Xap, Input = Self::Input>
fn runner_with_diagnostics( self, ) -> impl ParRec<Item = Self::Item, Xap = Self::Xap, Input = Self::Input>
Wraps the current parallel runner with a diagnostics-enabled runner.
The returned iterator behaves the same, but additionally reports runtime diagnostics at the end of the computation.
§Examples
use orx_parallel::*;
let par = par_recursive([1i32], |&x| (x < 10_000).then_some(x + 1))
.num_threads(4);
#[cfg(feature = "std")]
let par = par.runner_with_diagnostics();
let sum = par.sum::<i32>();
assert_eq!(sum, 50005000);This will print a summary report which currently looks like the following:
│ # Parallel Executor Diagnostics
│
│ Available threads : 4
│ Used threads : 4
│ Wall time : 1.15 ms
│
│ ## Summary Table
│ thread num_chunks num_tasks min_chunk avg_chunk max_chunk util%
│ ------ ---------- ---------- --------- --------- --------- -------
│ 0 35 27335 781 781 781 100.0%
│ 1 32 24992 781 781 781 91.5%
│ 2 30 23430 781 781 781 85.9%
│ 3 28 21868 781 781 781 77.8%
│
│ ## Workload Balance
│ max/min task ratio : 1.25x (1.00 = perfect balance)
│ coeff. of variation : 8.3% (lower is better)
│
│ ## Thread Active Timeline (each block ≈ 0.02 ms)
│ [ 0] ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇
│ [ 1] ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇
│ [ 2] ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇
│ [ 3] ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇
│
│ ## Thread Task Distribution (bar length ∝ tasks processed)
│ [ 0] ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ (27335)
│ [ 1] ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ (24992)
│ [ 2] ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ (23430)
│ [ 3] ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ (21868)Sourcefn num_threads(self, num_threads: impl Into<NumThreads>) -> Self
fn num_threads(self, num_threads: impl Into<NumThreads>) -> Self
Sets the maximum number of worker threads for this computation.
This method configures the computation layer of the thread count decision. The actual number of threads used is determined by combining:
- Pool constraint (from
pool()method or default pool)- Already includes
ORX_NUM_THREADSenvironment variable constraint
- Already includes
- Computation constraint (this method)
- Your per-computation thread preference
- Input size constraint
- Cannot spawn more threads than input elements
The actual thread count is the minimum of all these constraints.
§Parameter Interpretation
Integer values map as follows:
0=>NumThreads::Auto(use all available threads, spawn only as needed)n > 0=>NumThreads::Max(n)(cap atnthreads)
§Thread Count Decision Logic
available = pool.max_num_threads() // Pool maximum (includes env variable)
requested = match num_threads {
0 | Auto => input_size.max(1), // Limited by input size
Max(n) => min(input_size, n), // Limited by input size and this param
};
actual_threads = min(requested, available)§Examples
use orx_parallel::*;
// Sequential execution
let sum: usize = par_recursive([1usize], |&x| (x < 10).then_some(x + 1))
.num_threads(1)
.sum();
assert_eq!(sum, 55);
// Cap at 4 threads
let sum: usize = par_recursive([1usize], |&x| (x < 1000).then_some(x + 1))
.num_threads(4)
.sum();
// Auto: uses available threads (respects ORX_NUM_THREADS)
let sum: usize = par_recursive([1usize], |&x| (x < 10).then_some(x + 1))
.num_threads(0)
.sum();§See Also
NumThreads- Type for thread configurationthread_usage.md- Complete threading guide
Sourcefn chunk_size(self, chunk_size: impl Into<ChunkSize>) -> Self
fn chunk_size(self, chunk_size: impl Into<ChunkSize>) -> Self
Sets chunk size used when pulling items from the concurrent input.
Integer values map as follows:
0=> automatic (default)n > 0=> exact chunk sizen
§Examples
use orx_parallel::*;
let values: Vec<_> = par_recursive([0usize], |&x| (x < 31).then_some(x + 1))
.chunk_size(8)
.map(|x| x + 1)
.collect();
assert_eq!(values.len(), 32);
assert_eq!(values[0], 1);
assert_eq!(values[31], 32);§Rules of Thumb
- Automatic chunk size (default) is efficient in general. Parallel runner aims to find best chunk sizes to balance between minimizing parallelization overhead and maximizing resource utilization.
- While tuning a specific computation, we aim to find the smallest chunk size that is large enough to mitigate the impact of parallelization overhead.
- If the individual tasks are large enough, parallelization overhead becomes insignificant making
chunk_size = 1the optimal choice.
Sourcefn iteration_order(self, collect: IterationOrder) -> Self
fn iteration_order(self, collect: IterationOrder) -> Self
Sets iteration order semantics for operations sensitive to ordering.
Ordered (default) preserves positional meaning (for example, first returns the
earliest matching element in input order). Arbitrary allows any matching
element that is reached first in parallel execution.
§Examples
use orx_parallel::*;
let ordered = par_recursive([1i32], |&x| (x < 9_999).then_some(x + 1))
.iteration_order(IterationOrder::Ordered)
.find(|x| x % 3421 == 0);
assert_eq!(ordered, Some(3421));
let any = par_recursive([1i32], |&x| (x < 9_999).then_some(x + 1))
.iteration_order(IterationOrder::Arbitrary)
.find(|x| x % 3421 == 0)
.unwrap();
assert!([3421, 6842].contains(&any));Sourcefn map<Q, H>(
self,
h: H,
) -> impl ParRec<Item = Q, Xap = MapOf<Self::Xap, Q, H>, Input = Self::Input>
fn map<Q, H>( self, h: H, ) -> impl ParRec<Item = Q, Xap = MapOf<Self::Xap, Q, H>, Input = Self::Input>
Maps each element with closure h.
§Examples
use orx_parallel::*;
let doubled: Vec<_> = par_recursive([1i32], |&x| (x < 3).then_some(x + 1))
.map(|x| 2 * x)
.collect();
assert_eq!(doubled, vec![2, 4, 6]);Sourcefn inspect<H>(
self,
h: H,
) -> impl ParRec<Item = Self::Item, Xap = InsOf<Self::Xap, H>, Input = Self::Input>
fn inspect<H>( self, h: H, ) -> impl ParRec<Item = Self::Item, Xap = InsOf<Self::Xap, H>, Input = Self::Input>
Runs h on each element and forwards the item unchanged.
Useful for logging or debugging pipelines.
§Examples
use orx_parallel::*;
let out: Vec<_> = par_recursive([1i32], |&x| (x < 4).then_some(x + 1))
.inspect(|x| {
println!("observed {x}");
})
.collect();
assert_eq!(out, vec![1, 2, 3, 4]);Sourcefn filter<H>(
self,
h: H,
) -> impl ParRec<Item = Self::Item, Xap = FilOf<Self::Xap, H>, Input = Self::Input>
fn filter<H>( self, h: H, ) -> impl ParRec<Item = Self::Item, Xap = FilOf<Self::Xap, H>, Input = Self::Input>
Keeps only elements satisfying predicate h.
§Examples
use orx_parallel::*;
let odds: Vec<_> = par_recursive([1i32], |&x| (x < 6).then_some(x + 1))
.filter(|x| x % 2 == 1)
.collect();
assert_eq!(odds, vec![1, 3, 5]);Sourcefn filter_map<Q, H>(
self,
h: H,
) -> impl ParRec<Item = Q, Xap = FilMapOf<Self::Xap, Q, H>, Input = Self::Input>
fn filter_map<Q, H>( self, h: H, ) -> impl ParRec<Item = Q, Xap = FilMapOf<Self::Xap, Q, H>, Input = Self::Input>
Maps and filters in a single pass.
Returns mapped values for elements where h returns Some(_).
§Examples
use orx_parallel::*;
let numbers: Vec<_> = par_recursive(["1", "x", "5"], |_: &&str| None::<&str>)
.filter_map(|s| s.parse::<usize>().ok())
.collect();
assert_eq!(numbers, vec![1, 5]);Sourcefn flat_map<V, H>(
self,
h: H,
) -> impl ParRec<Item = V::Item, Xap = FlatMapOf<Self::Xap, V, H>, Input = Self::Input>
fn flat_map<V, H>( self, h: H, ) -> impl ParRec<Item = V::Item, Xap = FlatMapOf<Self::Xap, V, H>, Input = Self::Input>
Maps each element to an iterator and flattens one level.
§Examples
use orx_parallel::*;
let out: Vec<_> = par_recursive([1i32], |&x| (x < 3).then_some(x + 1))
.flat_map(|x| [x, x + 10])
.collect();
assert_eq!(out, vec![1, 11, 2, 12, 3, 13]);Sourcefn flatten(
self,
) -> impl ParRec<Item = <Self::Item as IntoIterator>::Item, Xap = FlattenOf<Self::Xap>, Input = Self::Input>where
Self::Item: IntoIterator,
fn flatten(
self,
) -> impl ParRec<Item = <Self::Item as IntoIterator>::Item, Xap = FlattenOf<Self::Xap>, Input = Self::Input>where
Self::Item: IntoIterator,
Flattens one level of nested iterables.
§Examples
use orx_parallel::*;
let nested = vec![vec![1, 2], vec![3, 4]];
let mut flat: Vec<_> = par_recursive(nested, |_: &Vec<i32>| None::<Vec<i32>>)
.flatten()
.collect();
flat.sort();
assert_eq!(flat, vec![1, 2, 3, 4]);Sourcefn first(self) -> Option<Self::Item>
fn first(self) -> Option<Self::Item>
Returns an item, or None if empty.
When IterationOrder::Ordered (default) is set, returns the first item in deterministic
breadth-first order (level by level, left-to-right following input and child generation order).
Setting IterationOrder::Arbitrary may provide speed improvements when ordering is not
important; however, ordered traversal is also optimized so the performance difference
is generally small.
This operation is short-circuiting: once a first candidate is determined, remaining work is cancelled.
§Examples
use orx_parallel::*;
let empty = par_recursive(Vec::<usize>::new(), |_: &usize| None::<usize>).first();
assert_eq!(empty, None);
let first = par_recursive([1usize], |&x| (x < 3).then_some(x + 1))
.first();
assert_eq!(first, Some(1));Sourcefn reduce<F>(self, f: F) -> Option<Self::Item>
fn reduce<F>(self, f: F) -> Option<Self::Item>
Reduces items into one value using associative reducer f.
Returns None for an empty iterator.
§Examples
use orx_parallel::*;
let reduced = par_recursive([1i32], |&x| (x < 5).then_some(x + 1))
.reduce(|a, b| a + b);
assert_eq!(reduced, Some(15));Sourcefn collect_into<P>(self, dst: &mut P)
fn collect_into<P>(self, dst: &mut P)
Collects all items into dst.
When IterationOrder::Ordered (default) is set, items are collected in a deterministic
breadth-first order (level by level, left-to-right following input and child generation order).
Setting IterationOrder::Arbitrary may provide speed improvements when ordering is not
important; however, ordered collection is also optimized so the performance difference
is generally small.
§Examples
use orx_parallel::*;
let mut dst = vec![10];
par_recursive([0i32], |&x| (x < 2).then_some(x + 1))
.collect_into(&mut dst);
assert_eq!(dst, vec![10, 0, 1, 2]);Sourcefn fold<B, I, F>(self, init: I, f: F) -> Vec<B>
fn fold<B, I, F>(self, init: I, f: F) -> Vec<B>
Folds elements into per-thread accumulators and returns them.
The output contains one accumulator for each participating worker.
§Examples
use orx_parallel::*;
let partials: Vec<usize> = par_recursive([1usize], |&x| (x < 5).then_some(x + 1))
.num_threads(2)
.fold(|| 0usize, |acc, x| *acc += x);
assert!(!partials.is_empty());
assert_eq!(partials.iter().sum::<usize>(), 15);Provided Methods§
Sourcefn collect<P>(self) -> P
fn collect<P>(self) -> P
Collects all items into a new collection.
When IterationOrder::Ordered (default) is set, items are collected in a deterministic
breadth-first order (level by level, left-to-right following input and child generation order).
Setting IterationOrder::Arbitrary may provide speed improvements when ordering is not
important; however, ordered collection is also optimized so the performance difference
is generally small.
§Examples
use orx_parallel::*;
let out: Vec<_> = par_recursive([1i32], |&x| (x < 3).then_some(x + 1))
.map(|x| x * 2)
.collect();
assert_eq!(out, vec![2, 4, 6]);Sourcefn all<F>(self, f: F) -> bool
fn all<F>(self, f: F) -> bool
Returns true if all items satisfy predicate f.
Empty iterators return true.
This operation is short-circuiting: evaluation stops as soon as one item fails the predicate.
§Examples
use orx_parallel::*;
assert!(par_recursive([1i32], |&x| (x < 4).then_some(x + 1))
.all(|x| x > &0));
assert!(!par_recursive([1i32], |&x| (x < 4).then_some(x + 1))
.all(|x| x % 2 == 0));Sourcefn any<F>(self, f: F) -> bool
fn any<F>(self, f: F) -> bool
Returns true if any item satisfies predicate f.
Empty iterators return false.
This operation is short-circuiting: evaluation stops as soon as one item satisfies the predicate.
§Examples
use orx_parallel::*;
assert!(par_recursive([1i32], |&x| (x < 4).then_some(x + 1))
.any(|x| x % 2 == 0));
assert!(!par_recursive([1i32], |&x| (x < 4).then_some(x + 1))
.any(|x| x > &10));Sourcefn count(self) -> usize
fn count(self) -> usize
Counts elements.
§Examples
use orx_parallel::*;
let n = par_recursive([1i32], |&x| (x < 10).then_some(x + 1))
.filter(|x| x % 3 == 0)
.count();
assert_eq!(n, 3);Sourcefn find<F>(self, f: F) -> Option<Self::Item>
fn find<F>(self, f: F) -> Option<Self::Item>
Finds the first item satisfying predicate f, or None if none match.
When IterationOrder::Ordered (default) is set, returns the first matching item in
deterministic breadth-first order (level by level, left-to-right following input and child
generation order).
Setting IterationOrder::Arbitrary may provide speed improvements when ordering is not
important; however, ordered traversal is also optimized so the performance difference
is generally small.
This is equivalent to self.filter(f).first().
This operation is short-circuiting: once a matching item is found, remaining work is cancelled.
§Examples
use orx_parallel::*;
let found = par_recursive([1i32], |&x| (x < 100).then_some(x + 1))
.find(|x| x % 17 == 0);
assert_eq!(found, Some(17));Sourcefn for_each<F>(self, f: F)
fn for_each<F>(self, f: F)
Executes f for each item.
§Examples
use core::sync::atomic::{AtomicUsize, Ordering};
use orx_parallel::*;
let total = AtomicUsize::new(0);
par_recursive([1usize], |&x| (x < 4).then_some(x + 1))
.for_each(|x| {
total.fetch_add(x, Ordering::Relaxed);
});
assert_eq!(total.load(Ordering::Relaxed), 10);Sourcefn max(self) -> Option<Self::Item>
fn max(self) -> Option<Self::Item>
Returns maximum element, or None if empty.
§Examples
use orx_parallel::*;
let max = par_recursive([1i32], |&x| (x < 4).then_some(x + 1))
.max();
assert_eq!(max, Some(4));
let empty = par_recursive(Vec::<usize>::new(), |_: &usize| None::<usize>)
.max();
assert_eq!(empty, None);Sourcefn max_by<F>(self, f: F) -> Option<Self::Item>
fn max_by<F>(self, f: F) -> Option<Self::Item>
Returns element considered maximum by comparator f.
§Examples
use orx_parallel::*;
let x = par_recursive(vec![-3_i32, 0, 1, 5, -10], |_: &i32| None::<i32>)
.max_by(|a, b| a.cmp(b));
assert_eq!(x, Some(5));Sourcefn max_by_key<B, F>(self, f: F) -> Option<Self::Item>
fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>
Returns element with maximum key value.
§Examples
use orx_parallel::*;
let x = par_recursive(vec![-3_i32, 0, 1, 5, -10], |_: &i32| None::<i32>)
.max_by_key(|x| x.abs());
assert_eq!(x, Some(-10));Sourcefn min(self) -> Option<Self::Item>
fn min(self) -> Option<Self::Item>
Returns minimum element, or None if empty.
§Examples
use orx_parallel::*;
let min = par_recursive([1i32], |&x| (x < 4).then_some(x + 1))
.min();
assert_eq!(min, Some(1));
let empty = par_recursive(Vec::<usize>::new(), |_: &usize| None::<usize>)
.min();
assert_eq!(empty, None);Sourcefn min_by<F>(self, f: F) -> Option<Self::Item>
fn min_by<F>(self, f: F) -> Option<Self::Item>
Returns element considered minimum by comparator f.
§Examples
use orx_parallel::*;
let x = par_recursive(vec![-3_i32, 0, 1, 5, -10], |_: &i32| None::<i32>)
.min_by(|a, b| a.cmp(b));
assert_eq!(x, Some(-10));Sourcefn min_by_key<B, F>(self, f: F) -> Option<Self::Item>
fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>
Returns element with minimum key value.
§Examples
use orx_parallel::*;
let x = par_recursive(vec![-3_i32, 0, 1, 5, -10], |_: &i32| None::<i32>)
.min_by_key(|x| x.abs());
assert_eq!(x, Some(0));Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".