0

I have the following code in Rust:

fn main() {
    let global = vec!(1, 2, 3);
    fn fn_a() {
        println!("{:?}", global);
        fn_b();
    };

    fn fn_b() {
        println!("{:?}", global);
        fn_a();
    };

    println!("Done.");
}

This does not compile because code in fn cannot capture global, and code in fn_b cannot capture fn_a.

I got the following error:

error[E0434]: can't capture dynamic environment in a fn item
   --> src/main.rs:193:24
    |
193 |         println!("{}", global);
    |                        ^^^^^^
    |
    = help: use the `|| { ... }` closure form instead

error[E0434]: can't capture dynamic environment in a fn item
   --> src/main.rs:198:24
    |
198 |         println!("{}", global);
    |                        ^^^^^^
    |
    = help: use the `|| { ... }` closure form instead

error: aborting due to 2 previous errors

(rustc --explain E0434)

So I changed to this:

fn main() {
    let global = vec!(1, 2, 3);

    let closure_a = || {
        println!("{:?}", global);
        closure_b();
    };

    let closure_b = || {
        println!("{:?}", global);
        closure_a();
    };

    println!("Done.");
}

but still got an error:

error[E0425]: cannot find function `closure_b` in this scope
   --> src/main.rs:195:9
    |
195 |         closure_b();
    |         ^^^^^^^^^ not found in this scope

error: aborting due to previous error

I guess this is because that the closure's scope begins from the line it is declared.

Is there a method to write a function/closure to call another function/closure which captures a global variable?

cmal
  • 2,062
  • 1
  • 18
  • 35
  • 1
    I don’t know if the answer to https://stackoverflow.com/questions/34847890/how-to-define-mutual-recursion-with-closures is up to date, but it’s related. – Ry- Jun 01 '20 at 08:20
  • I recommend against using closures here. While you can sometimes kind of make it work like in the answer of the linked question, you are much better off using either functions, passing in any additionally required data as extra parameters, or custom structs, if you really need to close over some data from the enclosing scope. This avoids the opaqueness, the limitations and the dynamic dispatch overhead of the answer in the linked question. – Sven Marnach Jun 01 '20 at 08:29
  • I've added another answer to the question tagged as duplicate. – Sven Marnach Jun 01 '20 at 08:47

1 Answers1

0

I have modified your code a little and it worked for me. I

fn fn_b(global:Vec<i32>) {
    println!(" From B: {:?}", global);
    fn_a(global);
}
fn fn_a(global:Vec<i32>) {
    println!("From A {:?}", global);
    fn_b(global);
}
fn main() {
    let global = vec!(1, 2, 3);
    fn_a(global);
    println!("Done.");
}

In the methodology, I am defining the fn_a and fn_b above the function main and passing the vector to a function from the main .

There is another method by adding static to keyword to your vector.

fn main() {
    static mut Global:Vec<i32> = Vec::new();
    unsafe {
        Global = vec!(1,2,3)
    }
    fn fn_a() {
        unsafe{
            println!("From A {:?}", Global);
            fn_b();
        }

    }
    fn fn_b() {
        unsafe{
            println!(" From B: {:?}", Global);
            fn_a();
        }

    }
    println!("Done.");
}

Check here the implementation of unsafe and also do remember calling your functions fn_a and fn_b

Kartikeya Sharma
  • 553
  • 1
  • 5
  • 22
  • Thank you very much for your help. But the reason I need a global is that I do not want to pass it to every function all over the world, if I only use it in one function of the bottom level. I haven't used any unsafe code before, I've have a try. BTW, are there any elegant way to do this? It seems not a very uncommon way to do such a thing in other language. – cmal Jun 01 '20 at 11:48