Как конвертировать замыкание без выхода в генератор? - PullRequest
0 голосов
/ 13 декабря 2018

Я пишу библиотеку, которая использует генераторы для хранения продолжений.Иногда я хочу передать замыкание без точек приостановки или без yield s, но компилятор жалуется, что замыкание не реализует черту Generator.

Я хочу скомпилировать следующий код бездобавление yield к закрытию;как я могу позволить компилятору обрабатывать замыкание как генератор?

#![feature(generators, generator_trait)]

use std::ops::Generator;

fn library_func(mut g: Box<dyn Generator<Yield = (), Return = ()>>) {
    let x = unsafe { g.resume() };
    println!("{:?}", x);
}

fn main() {
    // a closure without yield
    let x = Box::new(|| {
        // uncommenting this line makes it compile, but changes the behavior
        // yield ();
    });

    library_func(x);
}
error[E0277]: the trait bound `[closure@src/main.rs:12:22: 15:6]: std::ops::Generator` is not satisfied
  --> src/main.rs:17:18
   |
17 |     library_func(x);
   |                  ^ the trait `std::ops::Generator` is not implemented for `[closure@src/main.rs:12:22: 15:6]`
   |
   = note: required for the cast to the object type `dyn std::ops::Generator<Yield=(), Return=()>`

1 Ответ

0 голосов
/ 13 декабря 2018

Закрытие не является генератором, поэтому компилятор не может рассматривать его как единое целое.Неясно, должен ли генератор, который вы хотите реализовать, возвращать или давать возвращаемое значение функции;предполагая, что вы хотите первое, вы можете использовать оператор yield после оператора return, чтобы создать генератор, который не даст:

let x = Box::new(|| {
    return;
    yield;
});

Если вам это нужно часто, вы можете также обернуть это вфункция:

fn into_generator<F, T>(f: F) -> impl Generator<Yield = (), Return = T>
where
    F: FnOnce() -> T,
{
    #[allow(unreachable_code)]
    || {
        return f();
        yield;
    }
}

( Полный код на детской площадке )

...