цель для ленивых покрыта документацией для lazy
:
Создает новое будущее, которое в конечном итоге будет таким же, как и то, которое создано с помощью предоставленного закрытия.
Предоставленное закрытие запускается только тогда, когда на будущее запланирован обратный вызов, в противном случае обратный вызов никогда не выполняется. Однако после запуска это будущее совпадает с будущим, создаваемым закрытием.
Как простое замыкание, оно используется для предотвращения нетерпеливой оценки кода. В синхронных терминах это разница между вызовом функции и вызовом замыкания, которое вернула функция:
fn sync() -> impl FnOnce() {
println!("This is run when the function is called");
|| println!("This is run when the return value is called")
}
fn main() {
let a = sync();
println!("Called the function");
a();
}
И параллель для фьючерсов 0,1:
use futures::{future, Future}; // 0.1.27
fn not_sync() -> impl Future<Item = (), Error = ()> {
println!("This is run when the function is called");
future::lazy(|| {
println!("This is run when the return value is called");
Ok(())
})
}
fn main() {
let a = not_sync();
println!("Called the function");
a.wait().unwrap();
}
С синтаксисом async
/ await
эта функция больше не нужна:
#![feature(async_await)] // 1.37.0-nightly (2019-06-05)
use futures::executor; // 0.3.0-alpha.16
use std::future::Future;
fn not_sync() -> impl Future<Output = ()> {
println!("This is run when the function is called");
async {
println!("This is run when the return value is called");
}
}
fn main() {
let a = not_sync();
println!("Called the function");
executor::block_on(a);
}
Как вы определили, примеры Tokio используют lazy
для:
- убедитесь, что код в замыкании выполняется только изнутри исполнителя.
- гарантирует, что замыкание будет выполнено как будущее
Я считаю, что эти два аспекта lazy
фактически одинаковы.
Смотри также: