orx_iterable/obj_safe/collection_obj.rs
1use std::boxed::Box;
2
3/// A `CollectionObj` provides the [`boxed_iter`] method which returns a boxed iterator over shared references
4/// of elements of the collection.
5///
6/// It is the object safe counterpart of [`Collection`] trait which can conveniently be made into a trait object.
7///
8/// Note that for collections, `CollectionObj` is implicitly implemented and readily available.
9/// Please refer to [`Collection`] documentation for details of automatic implementations.
10///
11/// In order to use object safe iterables and collections please add `--features std` and use
12/// `use orx_iterable::{*, obj_safe::*}` to import dependencies rather than `use orx_iterable::*`.
13///
14/// [`Iterable`]: crate::Iterable
15/// [`Item`]: crate::obj_safe::CollectionObj::Item
16/// [`boxed_iter`]: crate::obj_safe::CollectionObj::boxed_iter
17/// [`Collection`]: crate::Collection
18///
19/// # Examples
20///
21/// ```
22/// use orx_iterable::obj_safe::*;
23/// use arrayvec::ArrayVec;
24/// use smallvec::{smallvec, SmallVec};
25/// use std::collections::{BTreeSet, BinaryHeap, HashSet, LinkedList, VecDeque};
26///
27/// struct Stats {
28/// count: usize,
29/// mean: i64,
30/// std_dev: i64,
31/// }
32///
33/// /// we need multiple iterations over numbers to compute the stats
34/// fn statistics(numbers: &dyn CollectionObj<Item = i64>) -> Stats {
35/// let count = numbers.boxed_iter().count() as i64;
36/// let sum = numbers.boxed_iter().sum::<i64>();
37/// let mean = sum / count;
38/// let sum_sq_errors: i64 = numbers.boxed_iter().map(|x| (x - mean) * (x - mean)).sum();
39/// let std_dev = f64::sqrt(sum_sq_errors as f64 / (count - 1) as f64) as i64;
40/// Stats {
41/// count: count as usize,
42/// mean,
43/// std_dev,
44/// }
45/// }
46///
47/// // example collections that automatically implement Collection
48///
49/// statistics(&[3, 5, 7]);
50/// statistics(&vec![3, 5, 7]);
51/// statistics(&LinkedList::from_iter([3, 5, 7]));
52/// statistics(&VecDeque::from_iter([3, 5, 7]));
53/// statistics(&HashSet::<_>::from_iter([3, 5, 7]));
54/// statistics(&BTreeSet::<_>::from_iter([3, 5, 7]));
55/// statistics(&BinaryHeap::<_>::from_iter([3, 5, 7]));
56///
57/// let x: SmallVec<[_; 128]> = smallvec![3, 5, 7];
58/// statistics(&x);
59///
60/// let mut x = ArrayVec::<_, 16>::new();
61/// x.extend([3, 5, 7]);
62/// statistics(&x);
63/// ```
64pub trait CollectionObj {
65 /// Type of elements stored by the collection.
66 type Item;
67
68 /// Creates a new iterator in a box yielding references to the elements of the collection; i.e.,
69 /// type of elements is `&Item`.
70 fn boxed_iter(&self) -> Box<dyn Iterator<Item = &Self::Item> + '_>;
71}
72
73impl<X> CollectionObj for X
74where
75 X: IntoIterator,
76 for<'a> &'a X: IntoIterator<Item = &'a <X as IntoIterator>::Item>,
77{
78 type Item = <X as IntoIterator>::Item;
79
80 fn boxed_iter(&self) -> Box<dyn Iterator<Item = &Self::Item> + '_> {
81 Box::new(<&X as IntoIterator>::into_iter(self))
82 }
83}