es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo debo retornar una función anónima desde una función padre para generar un cierre?

Explico mi pregunta con este fragmento de código. Desde main() funciona como espero. Ahora quiero mover eso a una función fuera de main(). No he encontrado la sintaxis de cómo debería ser la devolución. La documentación parece mostrar muchos enfoques, pero no puedo encontrar el exacto.

fn main() {
    println!("¡Hola Rust!");

    let mut _i = 0;
    let mut closure = || -> i32 {
        _i = _i + 1;
        _i
    };

    println!("El cierre devuelve: {}", closure());
    println!("El cierre devuelve: {}", closure());
    println!("El cierre devuelve: {}", closure());

    // OK, devuelve 1, 2, 3, ...

    // ahora quiero encapsular esto en una función, algo como:
    let fn_closure = get_counter();

    println!("La cerradura devuelve: {}", fn_closure());
    println!("La cerradura devuelve: {}", fn_closure());
    println!("La cerradura devuelve: {}", fn_closure());

    // expectativa: devuelve 1, 2, 3, ...
}

// intenta fallar - ¿cómo devuelve el cierre?
fn get_counter() -> impl Fn(i32) -> i32 { //? 
    let mut _i = 1;
    let f = move |i: i32| -> i32 {
        _i = _i + i;
        _i
    };
    f if n > 0 {
                _i = _i + i;
                _i
            } else {
                _i
            }
        };
    f
}

En otras palabras, me gustaría reproducir este mismo ejemplo escrito en C# pero en Rust.

Console.WriteLine("¡Hola C#!");

var closure = GetCounter();

Console.WriteLine("La cerradura devuelve: {0}", closure());
Console.WriteLine("La cerradura devuelve: {0}", closure());
Console.WriteLine("La cerradura devuelve: {0}", closure());

// OK, devuelve 1, 2, 3, ...

static Func<int> GetCounter()
{
    int i = 0;
    return () => ++i;
}

PD Tal vez sea una pregunta conceptual muy fácil, discúlpeme.

Tags:  ,

Answer

  1. Avatar for davy.ai

    El problema con el código es que el tipo de retorno de la función get_counter no está definido correctamente. Para devolver un cierre de una función en Rust, la sintaxis es la siguiente:

    fn get_counter() -> Box<dyn fnmut()="" -=""> i32> {
        let mut _i = 1;
        let mut f = || {
            _i = _i + 1;
            _i
        };
        Box::new(f)
    }
    

    Aquí, Box<dyn fnmut()="" -=""> i32> define el tipo de retorno de la función get_counter. FnMut() es un trait que define un cierre que puede ser llamado como función y puede mutar las variables capturadas. El cierre devuelto por get_counter no toma argumentos y devuelve un i32.

    Con este código actualizado, la función get_counter devolverá el cierre esperado, y la variable fn_closure en la función main se puede usar para invocar el cierre.

    fn main() {
        println!("¡Hola, Rust!");
    
        let mut _i = 0;
        let mut closure = || {
            _i = _i + 1;
            _i
        };
    
        println!("el cierre devuelve: {}", closure());
        println!("el cierre devuelve: {}", closure());
        println!("el cierre devuelve: {}", closure());
    
        let mut fn_closure = get_counter();
    
        println!("el cierre devuelve: {}", fn_closure());
        println!("el cierre devuelve: {}", fn_closure());
        println!("el cierre devuelve: {}", fn_closure());
        // se espera que devuelva 1, 2, 3, ...
    }
    
    fn get_counter() -> Box<dyn fnmut()="" -=""> i32> {
        let mut _i = 1;
        let mut f = || {
            _i = _i + 1;
            _i
        };
        Box::new(f)
    }
    

    Esto debería producir los resultados esperados.

Comments are closed.