Rust: Difference between revisions
No edit summary |
|||
| Line 1: | Line 1: | ||
=Trait Objects= |
=Trait Objects= |
||
Swapping between different ownership/reference types in Rust is a pain. The generics can ripple throughout a program making maintenance/refactoring a big hassle. |
Swapping between different ownership/reference types in Rust is a huge pain point. The generics can ripple throughout a program making maintenance/refactoring a big hassle. |
||
Consider some context that has a random number generator. I was wanting something similar for a Genetic programming experiment: |
Consider some context that has a random number generator. I was wanting something similar for a Genetic programming experiment: |
||
| Line 15: | Line 15: | ||
} |
} |
||
impl SomeTrait for Context { |
|||
| ⚫ | |||
//...Blah |
|||
fn some_function(self) {} |
|||
} |
|||
fn use_context(ctx: &Context) { |
|||
//...Blah |
|||
} |
|||
fn main() { |
|||
let mut ctx = Context::new(); |
|||
use_context(&ctx) |
|||
} |
|||
| ⚫ | |||
==Using Box's== |
==Using Box's== |
||
| Line 32: | Line 46: | ||
} |
} |
||
impl SomeTrait for Context { |
|||
//...Blah |
|||
} |
|||
fn use_context(ctx: &Context) { |
|||
//... |
//... |
||
} |
} |
||
| Line 40: | Line 58: | ||
let mut rng = StdRng::from_seed(seed); |
let mut rng = StdRng::from_seed(seed); |
||
let mut ctx = Context::new(Box::new(rng)); |
let mut ctx = Context::new(Box::new(rng)); |
||
use_context(&ctx) |
|||
} |
} |
||
| Line 46: | Line 65: | ||
Requires lifetime to be specified in generics. |
Requires lifetime to be specified in generics. |
||
== |
==Using trait's instead of the struct== |
||
Requires traits to be defined. Still needs generics on the structs functions such as the constructor. However user/consumers functions are uneffected. Other structs that own this struct must now deal with the same trait object problem. |
|||
pub struct ContextRaw { |
pub struct ContextRaw { |
||
} |
} |
||
==Using a global== |
|||
Doesn't allow for multiple different contexts with their own separate Rng generators. Maybe some thread_local variant would work but that seems to be a pain and a hack. Globals suck. |
|||
Revision as of 03:36, 10 December 2016
Trait Objects
Swapping between different ownership/reference types in Rust is a huge pain point. The generics can ripple throughout a program making maintenance/refactoring a big hassle.
Consider some context that has a random number generator. I was wanting something similar for a Genetic programming experiment:
pub struct Context {
rng: StdRng,
}
impl Context {
pub fn new() => Context {
let seed: &[_] = &[1, 2, 3, 4];
let mut rng = StdRng::from_seed(seed);
}
}
impl SomeTrait for Context {
//...Blah
fn some_function(self) {}
}
fn use_context(ctx: &Context) {
//...Blah
}
fn main() {
let mut ctx = Context::new();
use_context(&ctx)
}
This suffers from fixing the Rng to a specific implementation and prevents dependency inversion causing problems with things like testing and forcing any downstream users to be stuck with the choice.
Using Box's
Using boxes allows for generics to be avoided.
When adding a Box to the struct, it must be specified on the constructor, any mutator functions and the at the constructor call site. Users/consumers of the struct however are unaffected.
pub struct Context {
rng: Box<Rng>,
}
impl Context {
pub fn new(rng: Box<Rng>) -> Context {
Context {rng: rng}
}
}
impl SomeTrait for Context {
//...Blah
}
fn use_context(ctx: &Context) {
//...
}
fn main() {
let seed: &[_] = &[1, 2, 3, 4];
let mut rng = StdRng::from_seed(seed);
let mut ctx = Context::new(Box::new(rng));
use_context(&ctx)
}
Using &'s
Requires lifetime to be specified in generics.
Using trait's instead of the struct
Requires traits to be defined. Still needs generics on the structs functions such as the constructor. However user/consumers functions are uneffected. Other structs that own this struct must now deal with the same trait object problem.
pub struct ContextRaw {
}
Using a global
Doesn't allow for multiple different contexts with their own separate Rng generators. Maybe some thread_local variant would work but that seems to be a pain and a hack. Globals suck.