How do I make this closure work?

#![allow(dead_code)]
#![allow(unused_variables)]

use std::thread;
// use std::collections::HashMap;

#[async_std::main]
async fn main(){

    fn init(strategy_init: fn() -> fn(i32), strategy_config:()){

        let md_thread:thread::JoinHandle<_> = thread::spawn(move || {
    
            println!("{}", "spawn");
    
            let mut i:i32 = 0;

            let callback:fn(i32) = strategy_init();

            loop {
                
                if i >= 10_000 {
                    
                    break;
                }
                
                else {
                    
                    i += 1;

                    callback(i);
                }
            }
        });
    
        md_thread.join().unwrap();

    }

    init(|| {

        let mut x:i32 = 0;
        
        |n:i32| {

            x += 1;

            println!("::{}, {}", n, x);
        }
    
    }, ());

    println!("{}::", "Ok()");
}
error[E0308]: mismatched types
  --> src\main.rs:47:9
   |
47 | /         |n:i32| {
48 | |
49 | |             x += 1;
50 | |
51 | |             println!("::{}, {}", n, x);
52 | |         }
   | |_________^ expected fn pointer, found closure
   |
   = note: expected fn pointer `fn(i32)`
                 found closure `[closure@src\main.rs:47:9: 47:16]`
note: closures can only be coerced to `fn` types if they do not capture any variables
  --> src\main.rs:49:13
   |
49 |             x += 1;
   |             ^ `x` captured here

You cannot make the closure work. As the error message says, you need function pointer. The function pointer can be obtained by passing in a function's name (ie, the function item). Alternatively, it can be created from a closure that doesn't capture any value. However, your closure captures x.

Or, if you want to make arbitrary closures work, you should replace a plain function pointer fn with generics bounded by, or trait objects created from, one of the Fn traits (FnOnce, FnMut or Fn).

3 Likes

I hacked my way trough the compiler. Which was giving me helpful tips, along an article on closures...

But is this solution okay?

#![allow(dead_code)]
#![allow(unused_variables)]

use std::thread;
// use std::collections::HashMap;

#[async_std::main]
async fn main(){

    // let mut threads:() = ();
    // let mut system:() = ();

    fn init(strategy_init: fn() -> Box<dyn FnMut(i32)>, strategy_config:()){

        let md_thread:thread::JoinHandle<_> = thread::spawn(move || {
    
            println!("{}", "spawn");
    
            let mut i:i32 = 0;

            let mut callback:Box<dyn FnMut(i32)> = strategy_init();

            loop {
                
                if i >= 10_000 {
                    
                    break;
                }
                
                else {
                    
                    i += 1;

                    callback(i);
                }
            }
        });
    
        md_thread.join().unwrap();

    }

    init(|| {

        let mut x:i32 = 0;

        Box::new(move |n:i32| {

            x += 1;

            println!("::{}, {}", n, x);
        })
    
    }, ());

    println!("{}::", "Ok()");
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.