Library to support constant or closure

Hey there rustaceans.

I'm building a little utility to handle configuring a particle emitter, and I've found that I frequently would like to give the user the ability to specify a constant value or a closure like Fn() -> T + Send + Sync (to allow for a specific random distribution) for a given value. This is the module that I came up with to solve the problem and it works but it seems potentially unstable or that it fixes a problem that shouldn't exist, as is the classic engineer pitfall. I was wondering 1) if there's a library that covers this use-case that's more mature than my module and 2) if there's a better approach or design pattern for solving the issue of multiple optional levels of configurability.

Here's the code:

pub enum StaticOrClosure<T: Clone> {
  Static(T),
  Closure(Box<dyn Fn() -> T + Send + Sync>),
}

impl<T: Clone> StaticOrClosure<T> {
  pub fn get(&self) -> T {
    match self {
      StaticOrClosure::Static(value) => value.clone(),
      StaticOrClosure::Closure(closure) => closure().clone(),
    }
  }
}

impl<T: Clone> From<T> for StaticOrClosure<T> {
  fn from(value: T) -> Self {
    Self::Static(value)
  }
}

impl<T: Clone> From<Box<dyn Fn() -> T + Send + Sync>> for StaticOrClosure<T> {
  fn from(value: Box<dyn Fn() -> T + Send + Sync>) -> Self {
    Self::Closure(value)
  }
}

impl<T: Default + Clone> Default for StaticOrClosure<T> {
  fn default() -> Self {
    Self::Static(T::default())
  }
}

Thanks!

Experience shows that in this kind of situation, more and more kinds of "providers" will start to creep in over time. So instead of creating an enum to account for all possibilities, you could instead create a trait and be generic over that trait whenever required. (This would also avoid unnecessary and pervasive boxing ans dynamic dispatch.)

Another, simpler option is to simply offer two (or more) different methods whenever providing such a value is required, similar to Option::unwrap_or and Option::unwrap_or_else.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.