New to rust, how to handle default fields?

I'm new to Rust and would like to know what is currently idiomatic way of handling default "changes" field in Aggregate trait in code snippet below:

#[allow(non_camel_case_types)]
enum Event {
  COUNTER_DECREASE { amount: i32, },
  COUNTER_INCREASE { amount: i32, },
}

trait Aggregate {
  changes: Vec<Event>;

  fn apply(&mut self, e: Event);
  fn raise(&mut self, e: Event) {
    self.apply(e);
    self.changes.push(e);
  }
}

struct Counter {
  count: i32,
}

impl Counter {
  fn decrease(&mut self, amount: i32) {
    self.raise(Event::COUNTER_DECREASE { amount: amount });
  }

  fn increase(&mut self, amount: i32) {
    self.raise(Event::COUNTER_INCREASE { amount: amount });
  }
}

impl Aggregate for Counter {
  fn apply(&mut self, e: Event) {
    match e {
      Event::COUNTER_DECREASE { amount, .. } => self.count = self.count - amount,
      Event::COUNTER_INCREASE { amount, .. } => self.count = self.count + amount,
    }
  }
}

`

1 Like

Traits cannot store data, so this code doesn't actually work.

For default values, Default in std::default - Rust is the way to go.

#[derive(Default,Debug)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    // both of these lines work
    let p: Point = Default::default();
    let p = <Point as Default>::default();

    println!("{:?}", p);
}
1 Like

Exactly, code doesn't compile because of "changes" field in trait. I want "changes" field to be accessible for structs implementing Aggregate trait. Sorry, but I don't get how #[derive(Default)] could achieve that.

The traits cannot carry data, they're really just behavioral. A common solution to your example would be to have the Aggregate trait expect the type to define a fn changes(&mut self) -> &mut Vec<Event>;, or fn add_change(&mut self, e: Event); if you want to be storage-agnostic.

There is an RFC that would allow this, but for now you will need to include a changes field in the struct and add a .changes() method to the trait to access it.

https://github.com/rust-lang/rfcs/pull/1546

Thanks for your replies, much appreciated.

In the end I've settled with macro implemented for default "changes" field. Playground code snippet - Rust Playground for anyone interested or willing to comment on implementation.