What makes a rust compiler error: it is impossible to capture a dynamic environment in the fn element, instead use the closing form {{}} instead of "mean" and how to fix it?

I get a rust compiler error:

src/main.rs:33:31: 33:35 error: can't capture dynamic environment in a fn item; use the || { ... } closure form instead 

The error occurs because I have a function in which I declare a variable with let , and then have an internal function in which I try to use this variable, which is closed.

I am absolutely sure that this is a beginner's question, so sorry in advance if this has a very direct answer!

Please note that I am using this internal function as a callback somewhere and thus using closure like

 let closure_fn = | args | -> () { do stuff }; 

... would not be the right solution for me.


 extern crate nickel; use std::io::net::ip::Ipv4Addr; use nickel::{ Nickel, Request, Response }; fn stub_3rd_party_function() -> String { "hello world".to_string() } fn main() { let mut server = Nickel::new(); // assume that the variable **must** be instantiated like this let hello_text : String = stub_3rd_party_function(); fn hello_handler (_request: &Request, response: &mut Response) -> () { response.send(hello_text.as_slice()); } server.get("/hello", hello_handler); server.listen(Ipv4Addr(0,0,0,0), 6767); } 

Results with the following error:

 src/test.rs:12:23: 12:33 error: can't capture dynamic environment in a fn item; use the || { ... } closure form instead src/test.rs:12 response.send(hello_text); ^~~~~~~~~~ src/test.rs:12:23: 12:33 error: unresolved name `hello_text`. src/test.rs:12 response.send(hello_text); ^~~~~~~~~~ error: aborting due to 2 previous errors 

Now I switch from the standard function to the close function:

 extern crate nickel; use std::io::net::ip::Ipv4Addr; use nickel::{ Nickel, Request, Response }; fn stub_3rd_party_function() -> String { "hello world".to_string() } fn main() { let mut server = Nickel::new(); // assume that the variable **must** be instantiated like this let hello_text : String = stub_3rd_party_function(); let hello_handler = |_request: &Request, response: &mut Response| -> () { response.send(hello_text.as_slice()); }; server.get("/hello", hello_handler); server.listen(Ipv4Addr(0,0,0,0), 6767); } 

Results with another error:

 src/test.rs:21:30: 21:43 error: mismatched types: expected `fn(&nickel::request::Request<'_>, &mut nickel::response::Response<'_,'_>)` but found `|&nickel::request::Request<'_>, &mut nickel::response::Response<'_,'_>|` (expected extern fn but found fn) src/test.rs:21 server.get("/hello", hello_handler); ^~~~~~~~~~~~~ error: aborting due to previous error 

Is there a way to "wrap" a closed function with a normal one?

Since the library that I am using expects a standard function instead of closing, I cannot use closing. But if I do not use closure, I cannot close the variables that are defined inside the external function, fn main () { ... } ... and thus get stuck here.

Note that above, I use the hello_text string to provide an example of compressed code. In this case, it is sufficient to use a static variable. However, static variables will not fix this for me, since I need to be able to assign a variable from fn main() result of the function call, and then use it inside my internal handler function.

+6
source share
1 answer

It says that, since its a simple truth: a function cannot capture variables; if you put a function inside another function, then the function inside the function, and not outside, is simply a matter of namespace and makes it completely private and inaccessible to anything else. If you want to capture such a variable, you must use closure.

In your particular case, functions are the only way. You should consider your code like this (I would write it the same way to reduce indentation if nothing else):

 fn hello_handler(_request: &Request, response: &mut Response) { response.send(hello_text); } fn main() { let mut server = Nickel::new(); let hello_text = "hello world"; server.get("/hello", hello_handler); server.listen(Ipv4Addr(0, 0, 0, 0), 6767); } 

As you can see in this way of expression, hello_text is obviously not accessible from hello_handler . There are sound technical reasons why this is so - each request is processed in its own task. In this particular case, the solution is static:

 static HELLO_TEXT: &'static str = "hello world"; 
+2
source

Source: https://habr.com/ru/post/973199/


All Articles