Подтвердить что ты не робот

Подпись функции для возврата рекурсивного замыкания

Я пытаюсь реализовать функцию, которая возвращает рекурсивное закрытие. Хотя я не уверен, как выразить это в сигнатуре функции. Вот пример кода рабочей реализации в 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')

и псевдокод для Rust.

enum Msg {
    Inc,
    Dec
}

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

Ответ 1

Поскольку Rust поддерживает рекурсивные типы, вам просто нужно закодировать рекурсию в отдельной структуре:

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);
    }
}

Мы не можем покончить с боксом здесь, к сожалению - поскольку unboxed замыкания имеют непознаваемые типы, нам нужно поместить их в объект-признак, чтобы иметь возможность называть их внутри объявления структуры.