Могу ли я написать код ржавчины, эквивалентный приведенному ниже машинописному коду?

Вот код машинописного текста:

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);
    }
}

Но компилятор не позволяет такое предложение.

Что такое компоненты React? Введение в компоненты | Типы компонентов
Что такое компоненты React? Введение в компоненты | Типы компонентов
Компонент - это независимый, многократно используемый фрагмент кода, который делит пользовательский интерфейс на более мелкие части. Например, если мы...
2
0
72
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Возможный (и правильный) перевод будет таким:

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, и перевод кода буквально не сработает.

@FZs Потому что мы не можем выйти msg из Fn закрытия. Или, другими словами, потому что функция, возвращаемая gen(), может вызываться несколько раз.

Sven Marnach 06.02.2023 17:37

@SvenMarnach О, понятно!

FZs 07.02.2023 10:27

В Rust каждое замыкание имеет уникальный непрозрачный тип, даже если оно выглядит одинаково. async добавляет еще больше уникальности, поскольку асинхронные блоки создают уникальные анонимные типы, которые реализуют свойство Future.

Вы не можете указать возвращаемый тип функции gen, так как вы просто этого не знаете, компилятор генерирует тип за вас. Таким образом, решение, как продемонстрировал @ChayimFriedman в своем ответе, состоит в том, чтобы просто указать, что возвращаемый тип реализует некоторую черту (Fn в этом примере), или, в случае возвращаемого типа возвращаемого замыкания, стереть любой тип, который имеет асинхронный блок, используя черты объектов. dyn impl Future находится внутри Box, потому что он не имеет известного размера, а внешний Pin необходим, потому что возвращаемый тип Future должен иметь стабильное место в памяти, чтобы его можно было выполнить в асинхронном режиме выполнения (например, tokio или async-std).

Система типов Rust сильно отличается от системы typescript, асинхронность не встроена в язык, а реализована в виде различных библиотек, которые пользователь может использовать при необходимости. Вот почему прямой перевод между языками не всегда возможен.

Другие вопросы по теме