什么生锈编译器"错误:无法捕获fn项目中的动态环境;使用|| {...}闭包形式代替"意思,以及如何修复它?

boj*_*gle 7 syntax rust

我得到一个生锈编译错误:

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

发生错误是因为我有一个函数,我在其中声明一个变量使用let,然后有一个内部函数,我尝试使用这个被关闭的变量.

我相当肯定这是一个初学者的问题,如果这有一个非常直截了当的答案,请提前抱歉!

请注意,我正在使用此内部函数作为回调,因此使用闭包,如

let closure_fn = | args | -> () { do stuff };
Run Code Online (Sandbox Code Playgroud)

......对我来说不是一个合适的解决方案.


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);
}
Run Code Online (Sandbox Code Playgroud)

导致以下错误:

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
Run Code Online (Sandbox Code Playgroud)

现在,我从标准函数切换到闭包函数:

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);
}
Run Code Online (Sandbox Code Playgroud)

导致不同的错误:

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
Run Code Online (Sandbox Code Playgroud)

是否有一种方法可以用正常的方式"封闭"封闭的功能?

由于我使用的库需要一个标准函数而不是一个闭包,我不能使用闭包.但是如果我不使用闭包,我就无法关闭外部函数中定义的变量,fn main () { ... }......因而卡在这里.

请注意,上面,我使用的是字符串,hello_text以提供简洁的代码示例.在这种情况下,使用静态变量就足够了.但是,静态变量不会为我修复它,因为我需要能够在fn main()函数调用的结果中分配一个变量,然后在我的内部处理函数中使用它.

Chr*_*gan 3

它之所以这么说,是因为它\xe2\x80\x99 是一个简单的事实:函数无法捕获变量;函数无法捕获变量。如果将一个函数放入另一个函数中,则该函数位于该函数内部而不是外部,这纯粹是命名空间的问题,并使其绝对私有并且其他任何东西都无法访问。如果你想要这样的变量捕获,你必须使用闭包。

\n\n

在您的具体情况下,函数是唯一的方法。你应该考虑你的代码是这样的(我也会这样写,如果没有别的办法的话,以减少缩进):

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

正如您所看到的,通过这种表达方式,hello_text显然无法从hello_handler。有充分的技术原因说明为什么必须如此,而且\xe2\x80\x94每个请求都是在其自己的任务中处理的。在这种特殊情况下,静态是解决方案:

\n\n
static HELLO_TEXT: &\'static str = "hello world";\n
Run Code Online (Sandbox Code Playgroud)\n