ZhangHanDong / tao-of-rust-codes

《Rust编程之道》随书源码
https://ruststudy.github.io/tao_of_rust_docs/tao_of_rust/
MIT License
1.19k stars 172 forks source link

「第十一章」11.3.1生成器 代码清单11-62 Rust生成器用法变更 #259

Closed by23 closed 4 years ago

by23 commented 4 years ago

代码清单11-62 Rust生成器用法变更

以前的代码无法编译 新的代码如下

#![feature(generators, generator_trait)]
use std::ops::Generator;
use std::pin::Pin;

fn main() {
    let mut gen = || {
        yield 1;
        yield 2;
        yield 3;
        return 4;
    };
    for _ in 0..4 {
        let c = Pin::new(&mut gen).resume();
        println!("{:?}", c);
    }
}

运行结果如下

Yielded(1)
Yielded(2)
Yielded(3)
Complete(4)
ZhangHanDong commented 4 years ago

@by23 收到。感谢反馈

kid143 commented 4 years ago

现在这段代码也需要改一下,因为Generator这个trait的resume方法签名已经变更为: fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>; 这意味着需要传递arg参数给方法。

上面的代码变更为:

#![feature(generators, generator_trait)]
use std::ops::Generator;
use std::pin::Pin;

fn main() {
    let mut gen = || {
        yield 1;
        yield 2;
        yield 3;
        return 4;
    };
    for _ in 0..4 {
        // 多传入了一个空的unit给resume方法
        let c = Pin::new(&mut gen).resume(());
        println!("{:?}", c);
    }
}
ZhangHanDong commented 4 years ago

@kid143 感谢反馈

ZhangHanDong commented 4 years ago

@kid143 这个修改应该是为了支持 no_std 下的异步

ZhangHanDong commented 3 years ago
#![feature(generators, generator_trait)]
use std::ops::Generator;
use std::pin::Pin;

fn main() {
    let mut gen = || {
        yield 1;
        yield 2;
        yield 3;
        return 4;
    };
    for _ in 0..4 {
        // 多传入了一个空的unit给resume方法
        let c = Pin::new(&mut gen).resume(());
        println!("{:?}", c);
    }
}

生成的等价代码:

#![allow(unused)]
#![feature(generators, generator_trait)]
use std::ops::{Generator, GeneratorState};
use std::pin::Pin;

enum __Gen {
    // (0) 初始状态
    Start,
    // (1) resume方法执行以后
    State1(State1),
    // (2) resume方法执行以后
    State2(State2),
    // (3) resume方法执行以后
    State3(State3),
    // (4) resume方法执行以后,正好完成
    Done
}

struct State1 { x: u64 }
struct State2 { x: u64 }
struct State3 { x: u64 }

impl Generator for __Gen {
    type Yield = u64;
    type Return = u64;

    fn resume(self: Pin<&mut Self>, _: ()) -> GeneratorState<u64, u64> {
        let mut_ref = self.get_mut();
        match std::mem::replace(mut_ref, __Gen::Done) {
            __Gen::Start => {
                *mut_ref = __Gen::State1(State1{x: 1});
                GeneratorState::Yielded(1)
            }
            __Gen::State1(State1{x: 1}) => {
                *mut_ref  = __Gen::State2(State2{x: 2});
                GeneratorState::Yielded(2)
        }
            __Gen::State2(State2{x: 2}) => {
                *mut_ref = __Gen::State3(State3{x: 3});
                GeneratorState::Yielded(3)
            }
            __Gen::State3(State3{x: 3}) => {
                *mut_ref  = __Gen::Done;
                GeneratorState::Complete(4)
            }
            _ => {
                panic!("generator resumed after completion")
            }
        }
    }
}

fn main(){
    let mut gen = {
        __Gen::Start
    };

    for _ in 0..4 {
        println!("{:?}", unsafe{ Pin::new(&mut gen).resume(())});
    }
}