OneOrMany implemented in Rust
In the tuple |(d, embeddings)|
, the components correspond to the values yielded by documents.into_iter()
d
- This represents the original
Word
struct that was passed toEmbeddingsBuilder
. - Since
document(Word { ... })
was used,d
is an instance ofWord
, meaning it has fields likeid
anddefinition
.
- This represents the original
embeddings
- This represents the embeddings generated for
d
. - Since
EmbeddingsBuilder
likely produces a list of embeddings per document,embeddings
is a vector (Vec
) of embedding structures. - The
.first().vec
call suggests that each embedding inembeddings
has a field.vec
that contains the actual numerical embedding as aVec<f64>
.
- This represents the embeddings generated for
Thus:
d
→ AWord
struct (containingid
anddefinition
).embeddings
→ AVec<Embedding>
whereEmbedding
has a.vec
field that holds the actual numerical embedding.
Example of OneOrMany
Utility Type in Rust
use std::fmt::Debug;
// A utility enum to represent either one item or many items
#[derive(Debug)]
enum OneOrMany<T> {
One(T),
Many(Vec<T>),
}
impl<T> OneOrMany<T> {
// Method to check if we have a single item
fn is_one(&self) -> bool {
matches!(self, OneOrMany::One(_))
}
// Method to get the first item (either from One or Many)
fn first(&self) -> Option<&T> {
match self {
OneOrMany::One(ref item) => Some(item),
OneOrMany::Many(ref items) => items.first(),
}
}
// Method to map over the item(s) inside OneOrMany
fn map<U, F>(self, f: F) -> OneOrMany<U>
where
F: Fn(T) -> U,
{
match self {
OneOrMany::One(item) => OneOrMany::One(f(item)),
OneOrMany::Many(items) => OneOrMany::Many(items.into_iter().map(f).collect()),
}
}
}
// Example usage with an Embedding struct
#[derive(Debug, Clone)]
struct Embedding {
vec: Vec<f64>,
}
fn main() {
// Example 1: Single Embedding
let embedding_one = OneOrMany::One(Embedding {
vec: vec![1.0, 2.0, 3.0],
});
// Example 2: Multiple Embeddings
let embedding_many = OneOrMany::Many(vec![
Embedding { vec: vec![1.0, 2.0, 3.0] },
Embedding { vec: vec![4.0, 5.0, 6.0] },
]);
// Using `first` to get the first embedding
println!("First from one: {:?}", embedding_one.first());
println!("First from many: {:?}", embedding_many.first());
// Mapping over the items
let transformed = embedding_many.map(|embedding| Embedding {
vec: embedding.vec.iter().map(|x| x * 2.0).collect(),
});
println!("Transformed: {:?}", transformed);
}
Breakdown:
OneOrMany<T>
is an enum with two variants:One(T)
: Holds a single item of typeT
.Many(Vec<T>)
: Holds multiple items in a vector.
- Methods:
is_one
: Checks if the enum is holding a single item.first
: Returns a reference to the first item if present.map
: Allows transforming the items inside the enum.
- Example Usage:
- We create a
OneOrMany<Embedding>
for both a single embedding and multiple embeddings. - We demonstrate how
.first()
can be used to access the first element from either case. - We also show how
.map()
can be used to modify the values inside the enum.
- We create a
Example Output:
First from one: Some(Embedding { vec: [1.0, 2.0, 3.0] })
First from many: Some(Embedding { vec: [1.0, 2.0, 3.0] })
Transformed: Many([Embedding { vec: [2.0, 4.0, 6.0] }, Embedding { vec: [8.0, 10.0, 12.0] }])
In this case, OneOrMany
makes it flexible to handle cases where you might have a single embedding or multiple embeddings, while keeping the code concise and readable.
