ark_std/iterable/mod.rs
1//! A base library for interfacing with streams of vectors and matrices.
2//!
3//! This library presents the abstraction layer for the _streaming model_.
4//! Essentially, it provides a set of handy utilities as a wrapper around
5//! iterators.
6
7mod rev;
8pub use rev::Reverse;
9
10/// The trait [`Iterable`] represents a streamable object that can produce
11/// an arbitrary number of streams of length [`Iterable::len`](Iterable::len).
12///
13/// An Iterable is pretty much like an [`IntoIterator`] that can be copied over
14/// and over, and has an hint of the length. Copies are meant to be shared
15/// across threads safely.
16///
17/// # Examples
18///
19/// ```
20/// use ark_std::borrow::Borrow;
21/// use ark_std::iterable::Iterable;
22///
23/// // Relying only on standard library
24/// fn f(xs: impl IntoIterator<Item=impl Borrow<u32>> + Clone) -> u32 {
25/// xs.clone().into_iter().fold(1, |x, y| x.borrow() * y.borrow()) +
26/// xs.clone().into_iter().fold(0, |x, y| x.borrow() + y.borrow()) +
27/// xs.into_iter().size_hint().0 as u32
28/// }
29///
30/// // Relying on the trait below
31/// fn g(xs: impl Iterable<Item=impl Borrow<u32>>) -> u32 {
32/// xs.iter().fold(1, |x, y| x.borrow() * y.borrow()) +
33/// xs.iter().fold(0, |x, y| x.borrow() + y.borrow()) +
34/// xs.len() as u32
35/// }
36///
37/// // Test over a slice (which implements both traits).
38/// let xs = &[1, 2, 3, 4];
39/// assert_eq!(f(xs), g(xs));
40/// ```
41///
42/// # Efficency
43///
44/// For efficiency, functions using iterables are often times relying on
45/// [`Borrow`](std::borrow::Borrow) in order to avoid copying the contents of
46/// the iterator..
47///
48/// The `Iter` associated type has a lifetime that is independent from that of
49/// the [`Iterable`] object. This means that implicitly a copy of the relevant
50/// contents of the object will happen whenever
51/// [`Iterable::iter`](crate::iterable::Iterable::iter) is called. This might
52/// change in the future as associated type constructors
53/// [[RFC1598](https://github.com/rust-lang/rfcs/blob/master/text/1598-generic_associated_types.md#declaring--assigning-an-associated-type-constructor)]
54/// stabilize.
55///
56/// # Future implementation
57///
58/// A lot of stream operations must be performed symbolically.
59/// We expect that, in the future, this trait will accommodate for additional
60/// streaming function, e.g. `Iterable::hadamard(&self, other: &Iterable)` to
61/// perform the Hadamard product of two streams, or `Iterable::add(&self, other:
62/// &Iterable)` to perform the addition of two streams.
63pub trait Iterable: Send + Sync {
64 /// The type of the element being streamed.
65 type Item;
66 /// The type of the iterator being generated.
67 type Iter: Iterator<Item = Self::Item>;
68
69 /// Return the iterator associated to the current instance.
70 ///
71 /// In the so-called _streaming model_ [BCHO22], this is equivalent to
72 /// instantiating a new stream tape.
73 /// For base types, this acts in the same way as the `.iter()` method.
74 ///
75 /// ```
76 /// use ark_std::iterable::Iterable;
77 ///
78 /// let x = &[1, 2, 4];
79 /// let mut iterator = x.iter();
80 /// ```
81 fn iter(&self) -> Self::Iter;
82
83 /// Return a hint on the length of the stream.
84 ///
85 /// Careful: different objects might have different indications of what
86 /// _length_ means; this might not be the actual size in terms of
87 /// elements.
88 fn len(&self) -> usize;
89
90 /// Return `true` if the stream is empty, else `false`.
91 fn is_empty(&self) -> bool {
92 self.len() == 0
93 }
94}
95
96impl<I> Iterable for I
97where
98 I: IntoIterator + Copy + Send + Sync,
99 I::IntoIter: ExactSizeIterator,
100{
101 type Item = <I as IntoIterator>::Item;
102 type Iter = <I as IntoIterator>::IntoIter;
103
104 fn iter(&self) -> Self::Iter {
105 self.into_iter()
106 }
107
108 fn len(&self) -> usize {
109 self.into_iter().len()
110 }
111}