Skip to content

Instantly share code, notes, and snippets.

@marcbowes
Created February 12, 2014 05:28
Show Gist options
  • Save marcbowes/8950478 to your computer and use it in GitHub Desktop.
Save marcbowes/8950478 to your computer and use it in GitHub Desktop.
// This example demonstrates the following:
// 1) There is some API (modeled as a trait) we want our users to interact with
// 2) Something implements this trait
// 3) It depends on another trait to do some of it's work
// 4) That thing might be expensive and should be shareable across instances of #2
//
// This code compiles (Rust 0.10-pre)
pub trait Magician {
fn do_magic(&self);
}
pub struct Trevor;
impl Magician for Trevor {
fn do_magic(&self) {
// ...
}
}
pub trait MyApi {
fn tadaa(&self);
}
pub struct MyClient<'a, T> {
magician: &'a T
}
impl<'a, T: Magician> MyApi for MyClient<'a, T> {
fn tadaa(&self) {
self.magician.do_magic();
// and presumably something else
}
}
pub fn build_client<'a, T: Magician>(magician: &'a T) -> MyClient<'a, T> {
MyClient { magician: magician }
}
pub fn main() {
let trevor = Trevor;
let client = build_client(&trevor);
client.tadaa();
let another_client = build_client(&trevor);
another_client.tadaa();
}
// The problem with the above code is that the build_client method
// returns the implementation not the trait. This might result in code
// that is hard to test if the implementation does things like call out
// to the internet. We could fix this by casting:
let some_client = ~build_client(&trevor) as ~MyApi:;
some_client.tadaa();
// this is not ideal as it puts the responsibility on all users of the API
// I'd like to fix this in the build_client method, but this doesn't compile
pub fn build_client<'a, T: Magician>(magician: &'a T) -> ~MyApi: {
~MyClient { magician: magician } as ~MyApi:
}
pub fn main() {
let trevor = Trevor;
let client = build_client(&trevor);
client.tadaa();
}
// templated-traits.rs:29:5: 29:14 error: value may contain references; add `'static` bound
// templated-traits.rs:29 ~MyClient { magician: magician } as ~MyApi:
// ^~~~~~~~~
use std::rc::Rc;
pub trait Magician {
fn do_magic(&self);
}
pub struct Trevor;
impl Magician for Trevor {
fn do_magic(&self) {
// ...
}
}
pub trait MyApi {
fn tadaa(&self);
}
pub struct MyClient<T> {
magician: Rc<~T>
}
impl<T: Magician> MyApi for MyClient<T> {
fn tadaa(&self) {
self.magician.borrow().do_magic();
// and presumably something else
}
}
pub fn build_client<T: Magician>(magician: ~T) -> ~MyApi: {
~MyClient { magician: Rc::new(magician) } as ~MyApi:
}
pub fn main() {
let trevor = ~Trevor;
let client = build_client(trevor);
client.tadaa();
}
// templated-traits.rs:31:5: 31:14 error: value may contain references; add `'static` bound
// templated-traits.rs:31 ~MyClient { magician: Rc::new(magician) } as ~MyApi:
// ^~~~~~~~~
// This confuses me. Furthermore, I have no idea how to share trevor now because the build
// is going to move it out of main().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment