How to convert closure type to other type without calling?

Hi, could anyone help me?
I need to map a Vec of closures with one type to other Vec with another type of closures but I don't know how to do it, example: Rust Playground

    mod inner {

    #[derive(Debug)]
    pub enum InnerMsg {
        Value(i32)
    }
    
    pub fn update() -> Vec<impl Fn() -> InnerMsg> {
        vec![|| InnerMsg::Value(2)]
    }
}

#[derive(Debug)]
enum Msg {
    Inside(inner::InnerMsg),
    Other
}

impl From<inner::InnerMsg> for Msg {
    fn from(m: inner::InnerMsg) -> Self {
       Self::Inside(m) 
    }
}

pub fn update() -> Vec<impl Fn() -> Msg> {
    inner::update() // how to map msg type ?
}

fn main() {
  let cmds = update(); 
  
  for cmd in cmds {
     let msg = cmd();
     println!("{:?}", msg);
  }
}
pub fn update() -> Vec<impl Fn() -> Msg> {
    inner::update()      // -> Vec<impl Fn() -> inner::InnerMsg)
        .into_iter()     // -> impl Iterator<impl Fn() -> inner::InnerMsg>
        .map(|f| move || Msg::Inside(f()))
                         // -> impl Iterator<impl Fn() -> Msg>
        .collect()       // -> Vec<impl Fn() -> Msg>
}

The move || Msg::Inside(f()) lambda expression creates a new function that takes ownership of f (in each case, our original Fn() -> inner::InnerMsg function value) and yields a new function value that will, when evaluated, call f once, and wrap its return value in the Msg type.

Edit: Per your impl From, you can also write this as

pub fn update() -> Vec<impl Fn() -> Msg> {
    inner::update()      // -> Vec<impl Fn() -> inner::InnerMsg)
        .into_iter()     // -> impl Iterator<impl Fn() -> inner::InnerMsg>
        .map(|f| move || Msg::from(f()))
                         // -> impl Iterator<impl Fn() -> Msg>
        .collect()       // -> Vec<impl Fn() -> Msg>
}

to the same effect.

1 Like

Thanks man, that was simpler than I expected, on my code I used a Box<dyn Fn() -> Msg> instead of
impl Fn() -> Msg and this solution not worked, but I changed to impl Trait and just works. Thanks again.

1 Like

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.