Here's some example code for a simple struct World which contains a vector of Objects, for which each Object is assigned a category.
#[derive(PartialEq, Debug)]
enum Category {
    A, B, C, D
}
#[derive(Debug)]
struct Object {
    pub someData: f64,
    pub category: Category
    //...
}
struct World {
    pub objects: Vec<Object>,
    //...
}
impl World {
    pub fn new(objects: Vec<Object>) -> Self {
        World { objects }
    }
    pub fn getObjectsOfCategoryA(&self) -> Vec<&Object> {
        self.objects.iter().filter(|x| x.category == Category::A).collect()
    }
}
The World also offers the user the ability to query the objects of category A in particular.
But, what if I want to call getObjectsOfCategoryA() frequently enough that, for performance reasons, I want to cache the result of the function? Ideally this caching should be opaque to any caller of getObjectsOfCategoryA().
Let's add the restriction that objects is guaranteed not to be mutated after the World is created.
(I don't know how to express this restriction to Rust, but we'll get back to that later).
Object doesn't derive Copy or Clone so we can't just create a new vector of cloned objects as our cached vector.
One way to do it would be to use Arc:
struct World {
    objects: Vec<Arc<Object>>,
    objectsOfCategoryA: Vec<Arc<Object>>
}
impl World {
    pub fn new(objects: Vec<Object>) -> Self {
        let arcObjects: Vec<Arc<Object>> = objects.into_iter()
            .map(|x| Arc::new(x)).collect();
        let objectsOfCategoryA = arcObjects.iter().filter(|x| x.category == Category::A)
            .map(|x| x.clone()).collect();
        World { objects: arcObjects, objectsOfCategoryA }
    }
    pub fn getObjectsOfCategoryA(&self) -> &Vec<Arc<Object>> {
        &self.objectsOfCategoryA
    }
}
This strikes me as less than ideal because:
- We need to change the storage pattern of the main objectsvector
- This doesn't intuitively indicate to the reader of the code that objectsOfCategoryAis simply a view intoobjects
- If objectsis accidentally mutated, this will silently fail. Ideally, I'd like a compile error if anything tries to mutateobjectsafterWorldhas been constructed.
If there was some way for objectsOfCategoryA to be a Vec<&Object> that would feel 'right' to me, but from research I've done it seems like that's not possible.
I'm new to Rust, so it's quite possible I'm looking at this from too much of an OOP perspective. Can anyone indicate an idiomatic way to achieve this kind of caching?
 
     
    