如何将没有yield的闭包转换为生成器?

pan*_*man 2 closures generator rust

我正在编写一个使用生成器来保存延续的库。有时我想传递一个没有悬挂点或没有yields 的闭包,但编译器抱怨闭包没有实现该Generator特征。

我想编译以下代码而不yield在闭包中添加 a; 如何让编译器将闭包视为生成器?

#![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);
}
Run Code Online (Sandbox Code Playgroud)
#![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);
}
Run Code Online (Sandbox Code Playgroud)

Sve*_*ach 5

闭包不是生成器,因此编译器不能真正将其视为生成器。目前尚不清楚您希望实现的生成器是否应该返回产生函数的返回值;假设您想要前者,您可以在语句yield后使用语句return来创建不产生结果的生成器:

let x = Box::new(|| {
    return;
    yield;
});
Run Code Online (Sandbox Code Playgroud)

如果你经常需要这个,你也可以将它包装在一个函数中:

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

操场上的完整代码