pub enum Chunk<A> {
Empty,
Single(A),
Concat(Rc<Chunk<A>>, Rc<Chunk<A>>),
Collect(Rc<RefCell<Vec<A>>>),
TransformFlatten(Rc<Chunk<A>>, Rc<dyn Fn(A) -> Chunk<A>>),
}
Expand description
A persistent data structure that provides efficient append and concatenation operations.
§Overview
Chunk<A>
is an immutable data structure that allows O(1) complexity for append and
concatenation operations through structural sharing. It uses Rc
(Reference Counting)
for efficient memory management.
§Performance
- Append operation: O(1)
- Concatenation operation: O(1)
- Converting to Vec: O(n)
§Implementation Details
The data structure is implemented as an enum with three variants:
Empty
: Represents an empty chunkAppend
: Represents a single element appended to another chunkConcat
: Represents the concatenation of two chunks
§Examples
use tailcall_chunk::Chunk;
let mut chunk = Chunk::default();
chunk = chunk.append(1);
chunk = chunk.append(2);
let other_chunk = Chunk::default().append(3).append(4);
let combined = chunk.concat(other_chunk);
assert_eq!(combined.as_vec(), vec![1, 2, 3, 4]);
§References
Variants§
Empty
Represents an empty chunk with no elements
Single(A)
Represents a chunk containing exactly one element
Concat(Rc<Chunk<A>>, Rc<Chunk<A>>)
Represents the concatenation of two chunks, enabling O(1) concatenation
Collect(Rc<RefCell<Vec<A>>>)
Represents a collection of elements
TransformFlatten(Rc<Chunk<A>>, Rc<dyn Fn(A) -> Chunk<A>>)
Represents a lazy transformation that flattens elements
Implementations§
Source§impl<A> Chunk<A>
impl<A> Chunk<A>
Sourcepub fn is_null(&self) -> bool
pub fn is_null(&self) -> bool
Returns true
if the chunk is empty.
§Examples
use tailcall_chunk::Chunk;
let chunk: Chunk<i32> = Chunk::default();
assert!(chunk.is_null());
let non_empty = chunk.append(42);
assert!(!non_empty.is_null());
Sourcepub fn prepend(self, a: A) -> Self
pub fn prepend(self, a: A) -> Self
Prepend a new element to the beginning of the chunk.
This operation has O(1) complexity as it creates a new Concat
variant
that references the existing chunk through an Rc
.
§Examples
use tailcall_chunk::Chunk;
let chunk = Chunk::default().prepend(1).prepend(2);
assert_eq!(chunk.as_vec(), vec![2, 1]);
Sourcepub fn concat(self, other: Chunk<A>) -> Chunk<A>
pub fn concat(self, other: Chunk<A>) -> Chunk<A>
Concatenates this chunk with another chunk.
This operation has O(1) complexity as it creates a new Concat
variant
that references both chunks through Rc
s.
§Performance Optimization
If either chunk is empty, returns the other chunk instead of creating
a new Concat
variant.
§Examples
use tailcall_chunk::Chunk;
let chunk1 = Chunk::default().append(1).append(2);
let chunk2 = Chunk::default().append(3).append(4);
let combined = chunk1.concat(chunk2);
assert_eq!(combined.as_vec(), vec![1, 2, 3, 4]);
Sourcepub fn transform(self, f: impl Fn(A) -> A + 'static) -> Self
pub fn transform(self, f: impl Fn(A) -> A + 'static) -> Self
Transforms each element in the chunk using the provided function.
This method creates a lazy representation of the transformation without actually
performing it. The transformation is only executed when as_vec
or as_vec_mut
is called.
§Performance
- Creating the transformation: O(1)
- Executing the transformation (during
as_vec
): O(n)
§Arguments
f
- A function that takes a reference to an element of typeA
and returns a new element of typeA
§Examples
use tailcall_chunk::Chunk;
let chunk = Chunk::default().append(1).append(2).append(3);
// This operation is O(1) and doesn't actually transform the elements
let doubled = chunk.transform(|x| x * 2);
// The transformation happens here, when we call as_vec()
assert_eq!(doubled.as_vec(), vec![2, 4, 6]);
Sourcepub fn materialize(self) -> Chunk<A>where
A: Clone,
pub fn materialize(self) -> Chunk<A>where
A: Clone,
Materializes a chunk by converting it into a collected form.
This method evaluates any lazy transformations and creates a new chunk containing
all elements in a Collect
variant. This can be useful for performance when you
plan to reuse the chunk multiple times, as it prevents re-evaluation of transformations.
§Performance
- Time complexity: O(n) where n is the number of elements
- Space complexity: O(n) as it creates a new vector containing all elements
§Examples
use tailcall_chunk::Chunk;
let chunk = Chunk::default()
.append(1)
.append(2)
.transform(|x| x * 2); // Lazy transformation
// Materialize the chunk to evaluate the transformation once
let materialized = chunk.materialize();
assert_eq!(materialized.as_vec(), vec![2, 4]);
Sourcepub fn transform_flatten(self, f: impl Fn(A) -> Chunk<A> + 'static) -> Self
pub fn transform_flatten(self, f: impl Fn(A) -> Chunk<A> + 'static) -> Self
Transforms each element in the chunk into a new chunk and flattens the result.
This method creates a lazy representation of the transformation without actually
performing it. The transformation is only executed when as_vec
or as_vec_mut
is called.
§Performance
- Creating the transformation: O(1)
- Executing the transformation (during
as_vec
): O(n)
§Arguments
f
- A function that takes an element of typeA
and returns a newChunk<A>
§Examples
use tailcall_chunk::Chunk;
let chunk = Chunk::default().append(1).append(2);
// Transform each number x into a chunk containing [x, x+1]
let expanded = chunk.transform_flatten(|x| {
Chunk::default().append(x).append(x + 1)
});
assert_eq!(expanded.as_vec(), vec![1, 2, 2, 3]);
Sourcepub fn as_vec(&self) -> Vec<A>where
A: Clone,
pub fn as_vec(&self) -> Vec<A>where
A: Clone,
Converts the chunk into a vector of references to its elements.
This operation has O(n) complexity where n is the number of elements in the chunk.
§Examples
use tailcall_chunk::Chunk;
let chunk = Chunk::default().append(1).append(2).append(3);
assert_eq!(chunk.as_vec(), vec![1, 2, 3]);
Sourcepub fn as_vec_mut(&self, buf: &mut Vec<A>)where
A: Clone,
pub fn as_vec_mut(&self, buf: &mut Vec<A>)where
A: Clone,
Trait Implementations§
Source§impl<A> Default for Chunk<A>
impl<A> Default for Chunk<A>
Source§fn default() -> Self
fn default() -> Self
Creates a new empty chunk.
This is equivalent to using Chunk::Empty
.
Source§impl<A> FromIterator<A> for Chunk<A>
impl<A> FromIterator<A> for Chunk<A>
Source§fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self
Creates a chunk from an iterator.
§Examples
use tailcall_chunk::Chunk;
let vec = vec![1, 2, 3];
let chunk: Chunk<_> = vec.into_iter().collect();
assert_eq!(chunk.as_vec(), vec![1, 2, 3]);