There are situations where you want a factory function to create some data, but for whatever reasons the data you return must contain references. This does not seem possible because you cannot return references from functions.
Let's look at the following example code:
// Important: traits are of unknown size, and so must be passed around
// as a reference
trait Shape {
fn area(&self) -> f32;
}
// As seen here.
struct ShapeCollection<'a> {
shapes: Vec<&'a Shape>
}
// This function needs to return a ShapeCollection, but since the
// data structure requires references to work, it seems impossible!
fn make_shapes<'a>(needRectangle: bool, multiplier: f32) -> ShapeCollection<'a> {
let rect = Rectangle {
width: 42.0 * multiplier,
height: 24.0 * multiplier
};
let circle = Circle {
radius: 42.0 * multiplier
};
match needRectangle {
true => ShapeCollection {
shapes: vec![&rect, &circle]
},
false => ShapeCollection {
shapes: vec![&circle]
},
}
}
// ^ This function won't compile because rect and circle do not
// life long enough, and the compiler dies at this point
// Impls if you're interested / want to compile, but not that important
struct Rectangle {
width: f32,
height: f32
}
impl Shape for Rectangle {
fn area(&self) -> f32 {
self.width * self.height
}
}
struct Circle {
radius: f32
}
impl Shape for Circle {
fn area(&self) -> f32 {
(std::f32::consts::PI * self.radius).powf(2f32)
}
}
This is a simplified example built out of a more complex code I am writing. The gist of the issue is two conflating requirements:
- I need polymorphism. Since I'm using traits for this, and traits are not sized, the
Vec
must contain references not values - I need a factory function. Since I want to generate this list of objects from multiple parts of my code but with different parameters, it makes sense to make a function that encapsulates that, instead of copying and pasting logic around
How can I solve both of these requirements in Rust?
The two choices seems to be:
- Do something else to achieve polymorphism, something that is allowed to be passed around as a value
- De-duplicate multiple code blocks in some way that isn't creating a parameterised function