Вот код машинописного текста:
function gen(msg: string): () => Promise<void> {
return async function() {
// await any async function here ...
await sleep(1000);
console.info(msg);
}
}
Дословно переводится как ржавчина:
fn gen(msg: String) -> async fn() -> () {
async || {
sleep(1000).await;
println!("{}", msg);
}
}
Но компилятор не позволяет такое предложение.
Возможный (и правильный) перевод будет таким:
use std::future::Future;
use std::pin::Pin;
fn gen(msg: String) -> impl Fn() -> Pin<Box<dyn Future<Output = ()>>> {
move || {
let msg = msg.clone();
Box::pin(async move {
sleep(1000).await;
println!("{}", msg);
})
}
}
Но это не обязательно лучший. Rust — это не TypeScript, и перевод кода буквально не сработает.
@SvenMarnach О, понятно!
В Rust каждое замыкание имеет уникальный непрозрачный тип, даже если оно выглядит одинаково. async добавляет еще больше уникальности, поскольку асинхронные блоки создают уникальные анонимные типы, которые реализуют свойство Future.
Вы не можете указать возвращаемый тип функции gen
, так как вы просто этого не знаете, компилятор генерирует тип за вас. Таким образом, решение, как продемонстрировал @ChayimFriedman в своем ответе, состоит в том, чтобы просто указать, что возвращаемый тип реализует некоторую черту (Fn в этом примере), или, в случае возвращаемого типа возвращаемого замыкания, стереть любой тип, который имеет асинхронный блок, используя черты объектов. dyn impl Future
находится внутри Box, потому что он не имеет известного размера, а внешний Pin необходим, потому что возвращаемый тип Future должен иметь стабильное место в памяти, чтобы его можно было выполнить в асинхронном режиме выполнения (например, tokio
или async-std
).
Система типов Rust сильно отличается от системы typescript, асинхронность не встроена в язык, а реализована в виде различных библиотек, которые пользователь может использовать при необходимости. Вот почему прямой перевод между языками не всегда возможен.
@FZs Потому что мы не можем выйти
msg
изFn
закрытия. Или, другими словами, потому что функция, возвращаемаяgen()
, может вызываться несколько раз.