1

I explain my question with this code snippet. Since main() it works as I expect. Now I want to move that to a function outside of main(). I have not found the syntax how the return should be done. The documentation seems to show many approaches, but I can't find the exact one.

fn main() {
    println!("Hello, Rust!");

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

    println!("closure returns: {}", closure());
    println!("closure returns: {}", closure());
    println!("closure returns: {}", closure());

    // OK, returns 1, 2, 3, ...

    // now i want to encapsulate this in a function, something like:
    let fn_closure = get_counter();

    println!("closure returns: {}", fn_closure()); 
    println!("closure returns: {}", fn_closure()); 
    println!("closure returns: {}", fn_closure()); 

    // expect: returns 1, 2, 3, ...
}

// try failed - how returns the closure?
fn get_counter() -> || -> i32 { //? 
    let mut _i = 1;
    let mut f = || -> i32 {
        _i = _i + 1;
        _i
    };
    f
}

In other words, I would like to reproduce this same example written in C# but in Rust

Console.WriteLine("Hello, C#!");

var closure = GetCounter();

Console.WriteLine("closure returns: {0}", closure());
Console.WriteLine("closure returns: {0}", closure());
Console.WriteLine("closure returns: {0}", closure());

// OK, output is 1 , 2 , 3, ...

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

P.S. Perhaps it is a very easy conceptual question, excuse me.

  • Note that the leading underscore is conventionally used for identifiers you **don't** use. So `let mut _i` should rather be `let mut i`. – user4815162342 Nov 22 '21 at 14:58

1 Answers1

4

You can use the return type impl FnMut() -> i32. This can be seen as shorthand for “a concrete type that implements this trait(FnMut)”. In other teams we can use the impl Trait syntax in the return position to return a value of some type that implements a trait. Quoting from the documentation.

Closures and iterators create types that only the compiler knows or types that are very long to specify. The impl Trait syntax lets you concisely specify that a function returns some type that implements the Iterator trait without needing to write out a very long type.

fn main() {
    println!("Hello, Rust!");

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

    println!("closure returns: {}", closure());
    println!("closure returns: {}", closure());
    println!("closure returns: {}", closure());


    let mut fn_closure = get_counter();

    println!("closure returns: {}", fn_closure()); 
    println!("closure returns: {}", fn_closure()); 
    println!("closure returns: {}", fn_closure()); 

}

fn get_counter() -> impl FnMut() -> i32 {  
    let mut _i = 1;
    let f = move || -> i32 {
        _i = _i + 1;
        _i
    };
    f
}

See also

Abdul Niyas P M
  • 18,035
  • 2
  • 25
  • 46
  • It is exactly what I was looking for! – Alexandra Danith Ansley Nov 22 '21 at 15:46
  • 3
    @AlexandraDanithAnsley Please note, when a question has been answered to their satisfaction, the asker is expected to [accept](https://meta.stackexchange.com/a/5235/627709) the best answer. Doing so marks the question as resolved for future visitors, and awards the volunteer who provided the answer with a token reputation reward. – user4815162342 Nov 23 '21 at 13:12