Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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),
    }
}
like image 789
Brandon Ogle Avatar asked Mar 06 '16 20:03

Brandon Ogle


People also ask

How does a recursive function terminate?

A recursive termination is a condition that, when met, will cause the recursive function to stop calling itself. Because of the termination condition, countDown(1) does not call countDown(0) -- instead, the “if statement” does not execute, so it prints “pop 1” and then terminates.

Does a recursive function have to return something?

All functions - recursive or not - have one or more return . The return may or may not include a value. It is for you to decide when you write the function. All explicit written return statements must return the correct type.

Does return stop a recursive function?

Aside from that, if you've called your recursive function a given number of times, returning from the function would return you to the previous call of that function. A return statement won't stop all the prior recursive calls made from executing.


1 Answers

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.

like image 176
Vladimir Matveev Avatar answered Sep 19 '22 10:09

Vladimir Matveev