Tinus Wagner
Tinus Wagner

Reputation: 927

How do I evaluate and capture a function for later use in a loop?

I have the following function:

pub fn generate_mock_balances(interval: &Interval, n: &i32) -> Vec<HistoricBalance> {
  let time = Utc::now();
  let ticks = (1..*n).map(|v| v as i64);
  let mut mocks = vec![];

  for tick in ticks {
      let historic_time = match interval {
          Interval::Hour => time - Duration::minutes(tick),
          Interval::Day => time - Duration::hours(tick),
          Interval::Week => time - Duration::days(tick),
          Interval::Month => time - Duration::weeks(tick),
          Interval::Year => time - Duration::weeks(4 * tick),
      };

      mocks.push(HistoricBalance {
          time: historic_time.timestamp().to_string(),
          balance: (1499 * tick).to_string(),
      });
  }

  mocks
}

I feel like the switch case within the loop is not efficient and that there must be a way to select the appropriate Duration function once and store it for use in the loop, instead of doing the check at every iteration of the loop.

I've taken a look at the documentation for closures and while I instinctively feel it's the way to go it seems more suited towards speeding up slow calculations by storing the outcome of said calculation for re-use. How do I do this?

Upvotes: 2

Views: 154

Answers (1)

Akida
Akida

Reputation: 1116

You can match the interval once and save the function in a variable:

let duration_fn = match interval {
      Interval::Hour => Duration::minutes,
      Interval::Day => Duration::hours,
      Interval::Week => Duration::days,
      Interval::Month => Duration::weeks,
      Interval::Year => |tick: i64| Duration::weeks(4 * tick),
  };

and use the function in the loop:

let historic_time = time - duration_fn(tick);

If you want you could simplify the creation of ticks:

let ticks = 1i64..*n as i64;

playground

Upvotes: 3

Related Questions