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 using let
, and then have an inner function in which I try to use this variable that is closed over.
I am fairly certain that this is a beginner question, so sorry in advance if this has a very straight forward answer!
Note that I am using this inner function as a callback somewhere, and thus using a closure, like
let closure_fn = | args | -> () { do stuff };
... is not going to be an appropriate 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 in 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 a standard function to a closure function instead:
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 in a different 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 perhaps a way to "wrap" the closed over function with a normal one?
Since the library that I am using expects a standard function instead of a closure,
I cannot use a closure.
But if I do not use a closure, I cannot close over variables that are defined within the outer function, fn main () { ... }
... and thus getting stuck here.
Note that above, I am using a string, hello_text
, for the purposes of providing a concise code example.
In this case using a static variable would suffice. However, static variables will not fix it for me, as I need to be able to assign a variable from within a fn main()
the result of a function call, and then use that within my inner handler function.
It says that because it’s the simple truth: a function cannot capture variables; if you put a function inside another function, that the function is inside the function rather than outside is purely a matter of namespacing and making it absolutely private and inaccessible to anything else. If you want such variable capturing, you must use a closure.
In your specific case, functions are the only way. You should consider your code to be this (I would write it this way, too, 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 with this way of expressing it, hello_text
is evidently inaccessible from hello_handler
. There are sound technical reasons why it must be so, also—each request is handled in its own task. In this particular case, a static is the solution:
static HELLO_TEXT: &'static str = "hello world";
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With