Help for creating objects inside a struct (Something similar to creating objects inside constructor in Java)

Lost on How to approach this problem in Rust? Need to create a specific instance of Trait Type T

#[derive(Debug)]
pub struct MACDIndicator<'macd, T>
    where T: Indicator {
    indicator: &'macd mut T,
    short_term_period: usize,
    long_term_period: usize,
    signal_line_period: usize,
    calc_indicator_values: Vec<Option<f64>>,
    calc_macd_values: Vec<Option<f64>>,
    calc_signal_values: Vec<Option<f64>>,
    calc_histogram_values: Vec<Option<f64>>,
    short_term_ema_indicator: &'macd mut EMAIndicator<'macd, T>,
    long_term_ema_indicator: &'macd mut EMAIndicator<'macd, T>
}

impl<'macd, T> MACDIndicator<'macd, T>
    where T: Indicator {
    pub fn new(indicator: &'macd mut T) -> Self {
        Self {
            indicator,
            short_term_period: 12,
            long_term_period: 26,
            signal_line_period: 9,
            calc_indicator_values: Vec::new(),
            calc_macd_values: Vec::new(),
            calc_signal_values: Vec::new(),
            calc_histogram_values: Vec::new(),
            short_term_ema_indicator: &mut EMAIndicator::new(indicator, 12),
            long_term_ema_indicator: &mut EMAIndicator::new(indicator, 26)
        }
    }

Error but the question is more on is the design wrong and how to approach this problem in Rust.

error[E0515]: cannot return value referencing temporary value
   --> src/traits.rs:529:9
    |
529 | /         Self {
530 | |             indicator,
531 | |             short_term_period: 12,
532 | |             long_term_period: 26,
...   |
539 | |             long_term_ema_indicator: &mut EMAIndicator::new(indicator, 26)
    | |                                           -------------------------------- temporary value created here
540 | |         }
    | |_________^ returns a value referencing data owned by the current function

error[E0515]: cannot return value referencing temporary value
   --> src/traits.rs:529:9
    |
529 | /         Self {
530 | |             indicator,
531 | |             short_term_period: 12,
532 | |             long_term_period: 26,
...   |
538 | |             short_term_ema_indicator: &mut EMAIndicator::new(indicator, 12),
    | |                                            -------------------------------- temporary value created here
539 | |             long_term_ema_indicator: &mut EMAIndicator::new(indicator, 26)
540 | |         }
    | |_________^ returns a value referencing data owned by the current function

error[E0499]: cannot borrow `*indicator` as mutable more than once at a time
   --> src/traits.rs:538:62
    |
526 |   impl<'macd, T> MACDIndicator<'macd, T>
    |        ----- lifetime `'macd` defined here
...
529 | /         Self {
530 | |             indicator,
    | |             --------- first mutable borrow occurs here
531 | |             short_term_period: 12,
532 | |             long_term_period: 26,
...   |
538 | |             short_term_ema_indicator: &mut EMAIndicator::new(indicator, 12),
    | |                                                              ^^^^^^^^^ second mutable borrow occurs here
539 | |             long_term_ema_indicator: &mut EMAIndicator::new(indicator, 26)
540 | |         }
    | |_________- returning this value requires that `*indicator` is borrowed for `'macd`

error[E0499]: cannot borrow `*indicator` as mutable more than once at a time
   --> src/traits.rs:539:61
    |
526 |   impl<'macd, T> MACDIndicator<'macd, T>
    |        ----- lifetime `'macd` defined here
...
529 | /         Self {
530 | |             indicator,
    | |             --------- first mutable borrow occurs here
531 | |             short_term_period: 12,
532 | |             long_term_period: 26,
...   |
539 | |             long_term_ema_indicator: &mut EMAIndicator::new(indicator, 26)
    | |                                                             ^^^^^^^^^ second mutable borrow occurs here
540 | |         }
    | |_________- returning this value requires that `*indicator` is borrowed for `'macd`

error: aborting due to 4 previous errors; 11 warnings emitted

Some errors have detailed explanations: E0499, E0515.
For more information about an error, try `rustc --explain E0499`.

It works this way, but how do I use the field short_term_period to create EMAIndicator

#[derive(Debug)]
pub struct MACDIndicator<'macd, T>
    where T: Indicator {
    indicator: &'macd mut T,
    short_term_period: usize,
    long_term_period: usize,
    signal_line_period: usize,
    calc_indicator_values: Vec<Option<f64>>,
    calc_macd_values: Vec<Option<f64>>,
    calc_signal_values: Vec<Option<f64>>,
    calc_histogram_values: Vec<Option<f64>>,
    short_term_ema_indicator: EMAIndicator<'macd, T>,
    long_term_ema_indicator: EMAIndicator<'macd, T>
}

impl<'macd, T> MACDIndicator<'macd, T>
    where T: Indicator {
    pub fn new(indicator: &'macd mut T, indicator1: &'macd mut T, indicator2: &'macd mut T) -> Self {
        Self {
            indicator,
            short_term_period: 12,
            long_term_period: 26,
            signal_line_period: 9,
            calc_indicator_values: Vec::new(),
            calc_macd_values: Vec::new(),
            calc_signal_values: Vec::new(),
            calc_histogram_values: Vec::new(),
            short_term_ema_indicator: EMAIndicator::new(indicator1, 12),
            long_term_ema_indicator:EMAIndicator::new(indicator2, 26)
        }
    }

    // pub fn init(&mut self) {
    //     self.short_term_ema_indicator: &mut EMAIndicator::new(indicator, 12),
    //     self.long_term_ema_indicator: &mut EMAIndicator::new(indicator, 26)
    // }

    // pub fn new_custom_periods(indicator: &'macd mut T, short_term_period: usize, long_term_period: usize, signal_line_period: usize) -> Self {
    //     Self {
    //         indicator,
    //         short_term_period,
    //         long_term_period,
    //         signal_line_period,
    //         calc_indicator_values: Vec::new(),
    //         calc_macd_values: Vec::new(),
    //         calc_signal_values: Vec::new(),
    //         calc_histogram_values: Vec::new(),
    //     }
    // }
}

If you want to take ownership of the EMAIndicator variable, then don't use a reference. References are only for temporary borrows.

1 Like

Can you please fix the formatting by editing your post, rather than posting a new one?

1 Like