I am doing some statistics and working with random samples. Here is some typical auxiliary code:
pub fn gen_log_sample(sample_size: usize, k: usize) -> Vec<f64> {
let mut sample = frechet(1.1, sample_size);
sample.order_stat_top(k).normalize().ln();
sample.unwrap()
}
The frechet(α, n)
function returs a Sample
, which is just a struct wrapper around Vec<f64>
. I do this to impl
several transformations on the Sample
. Each transformation takes &mut self
and returns self
as a &mut Sample
to allow chaining. I took the inspiration for this from the gnuplot
library. The final unwrap
takes ownership self
, removes the wrapper and returns the raw Vec<f64>
.
This is already way nicer than what I had before, but I'm still unhappy about the chaining. I would love to write
pub fn gen_log_sample(sample_size: usize, k: usize) -> Vec<f64> {
// This code does not compile!
let mut sample = frechet(1.1, sample_size)
.order_stat_top(k)
.normalize()
.ln()
.unwrap()
}
This would get me to the point where I wouldn't even need those ill-named auxiliary functions like gen_log_sample(..)
anymore. But there are some problems caused by ownership/borrowing: I can't combine the first two lines (sampling & transformations), because then no one owns the Sample. Neither can I combine transformations & unwrapping, because unwrap needs to take ownership, and transformations don't yield ownership.
I would love to hear your ideas how I can improve my API for this. (I feel like there probably is some trait magic to guide me)