12

New to Rust here, apologies for my naiveté.

I want to define some probability distributions, which obviously have differing parameters. But the "interface" (as I know it in Java) should be the same. At the most basic level each distribution should have a sample and a sample_many method. So I implement a trait:

pub trait ERP<T> {
    fn sample(&self) -> T;
    fn sample_many(&self, i: isize) -> Vec<T>;
}

Then a specific distribution can be created:

pub struct Bernoulli {
    pub p: f64
}

impl ERP<bool> for Bernoulli {
    fn sample(&self) -> bool {
        rand::random::<f64>() < self.p
    }

    fn sample_many(&self, i: isize) -> Vec<bool> {
        (0..i).map(|_| self.sample()).collect()
    }
}

My issue is with the sample_many method, specifically. This method will be the same code regardless of the kind of distribution, e.g.

pub struct Gaussian {
    pub mu: f64,
    pub sigma: f64
}

impl ERP<f64> for Gaussian {
    fn sample(&self) -> f64 {
        // Code unique to each distribution
    }

    fn sample_many(&self, i: isize) -> Vec<f64> {
        (0..i).map(|_| self.sample()).collect() // Code reuse??
    }
}

So copying the method here is pretty redundant. Is there a way around this?

jayelm
  • 7,236
  • 5
  • 43
  • 61
  • @ker My intent was not to create a compilable example, but just an example for a generalizable issue, hence leaving out `sample` in `Gaussian` – jayelm Jul 02 '15 at 13:30
  • rust has the `unimplemented!()` macro for such situations. Your code will compile, but do nothing useful. you can see this in http://is.gd/WwsBW2 – oli_obk Jul 02 '15 at 13:31
  • For code that is very similar, sometimes an implementation macro makes sense. Though, I think that @ker's default implementation is the most appropriate here. (see macro question: http://stackoverflow.com/questions/31082179/implementing-a-trait-for-a-trait ) – jocull Jul 02 '15 at 15:24

1 Answers1

10

You can create a default implementation for any function in the trait definition. It can still be overwritten by an implementor

pub trait ERP<T> {
    fn sample(&self) -> T;
    fn sample_many(&self, i: isize) -> Vec<T> {
        (0..i).map(|_| self.sample()).collect()
    }
}
oli_obk
  • 28,729
  • 6
  • 82
  • 98