到目前为止,我认为move |...| {...}
会在闭包内移动变量,闭包只会实现FnOnce
,因为你只能移动变量一次。然而,令我惊讶的是,我发现此代码有效:
extern crate futures;
use futures::stream;
use futures::stream::{Stream, StreamExt};
use std::rc::Rc;
#[derive(Debug)]
struct Foo(i32);
fn bar(r: Rc<Foo>) -> Box<Stream<Item = (), Error = ()> + 'static> {
Box::new(stream::repeat::<_, ()>(()).map(move |_| {
println!("{:?}", r);
}))
}
fn main() {
let r = Rc::new(Foo(0));
let _ = bar(r);
}
尽管map
有这个签名:
fn map<U, F>(self, f: F) -> Map<Self, F>
where
F: FnMut(Self::Item) -> U,
令我惊讶的是,在使用FnMut
关键字时创建了move
封闭,它的生命周期甚至为'static
。我在哪里可以找到有关move
的一些详细信息?或者它是如何运作的?
答案 0 :(得分:7)
是的,这一点非常令人困惑,我认为Rust书的措辞有所贡献。在我阅读之后,我的想法和你一样:move
闭包必须是FnOnce
,而非move
闭包是FnMut
(也可能是Fn
)。但这与实际情况有点相反。
闭包可以从创建它的范围捕获值。 move
控制这些值如何进入闭包:移动或引用。但是它们是如何在之后使用来捕获它们来确定闭包是否为FnMut
。
如果闭包的主体消耗它捕获的任何值,则闭包只能是FnOnce
。关闭第一次运行后,消耗该值,它不能再次运行。
正如您所提到的,您可以通过调用drop
或其他方式在闭包内部使用一个值,但最常见的情况是从闭包中返回它,从而将其移出关闭。这是最简单的例子:
let s = String::from("hello world");
let my_fnonce = move || { s };
如果闭包的主体没有消耗任何捕获,那么它是FnMut
,无论是move
还是Fn
。如果它也没有改变任何捕获,它也是Fn
;任何FnMut
的闭包也是let s = "hello world";
let my_fn = move || { s.length() }
。这是一个简单的例子,虽然不是很好的例子。
move
FnMut
修饰符控制在创建时,如何将捕获移动到关闭。 <VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example/
<Location /node>
ProxyPass http://127.0.0.1:8124/
ProxyPassReverse http://127.0.0.1:8124/
</Location>
</VirtualHost>
成员资格取决于捕获在执行时如何从移出关闭(或以其他方式消费)。
答案 1 :(得分:4)
到目前为止,我认为
<div class="para"> </div>
将在闭包内移动变量,闭包只会实现.para{ z-index: -100; height: 160vh; width: 100%; margin-top: -40rem; background: url("back1.jpg") no-repeat center; background-size: cover; background-attachment: fixed; -webkit-clip-path: polygon(0 22%, 100% 0, 100% 79%, 0% 100%); clip-path: polygon(0 22%, 100% -800px, 100% 60%, 0% 100%); transform: rotate(10deg); }
,因为你只能移动一次变量。
创建闭包时移动变量,而不是在调用它时移动。由于您只创建了一个闭包,因此移动只发生一次 - 无论move |...| {...}
调用该函数的频率如何。