Search code examples
recursiontypesclosuresrustcontinuations

Function signature for returning a recursive closure


I am attempting to implement a function that returns a recursive closure., though I am not sure how to express that in the function signature. Here is example code of a working implementation in Python

def counter(state):
    def handler(msg):
        if msg == 'inc':
            print state
            return counter(state + 1)

        if msg == 'dec':
            print state
            return counter(state - 1)
    return handler

c = counter(1)
for x in range(1000000):
    c = c('inc')

and pseudo code for Rust.

enum Msg {
    Inc,
    Dec
}

fn counter(state: Int) -> ? {
    move |msg| match msg {
        Msg::Inc => counter(state + 1),
        Msg::Dec => counter(state - 1),
    }
}

Solution

  • Because Rust supports recursive types, you just need to encode the recursion in a separate structure:

    enum Msg { 
        Inc,
        Dec,
    }
    
    // in this particular example Fn(Msg) -> F should work as well
    struct F(Box<FnMut(Msg) -> F>);
    
    fn counter(state: i32) -> F {
        F(Box::new(move |msg| match msg {
            Msg::Inc => {
                println!("{}", state);
                counter(state + 1)
            }
            Msg::Dec => {
                println!("{}", state);
                counter(state - 1)
            }
        }))
    }
    
    fn main() {
        let mut c = counter(1);
        for _ in 0..1000 {
            c = c.0(Msg::Inc);
        }
    }
    

    We cannot do away with boxing here, unfortunately - since unboxed closures have unnameable types, we need to box them into a trait object to be able to name them inside the structure declaration.