Can we model the complete function of yield by using await in rust?

In the C++ coroutine, the keyword yield function is based on the grammar sugar that uses co_await. So, I wonder whether it is possible to model the complete feature of yield by using await in rust? My idea is that

async fn get_value(v:Rc<RefCell<i32>>)->(){
    for i in 1..10{
      *v.borrow_mut() = i;
      Awaitable.await; // #1
   }
}
fn main(){
   let i = Rc::new(RefCell::new(0));
   let f = Box::pin(get_value(Rc::clone(&i)));
   loop{
     match f.as_mut().poll(cx){
          Poll::Ready(x) => break x,
	      Poll::Pending => {
		    let r = *i.borrow();
		    println!("{r}");
	      },
     }
   };
}

Each time the flow control passes #1, it will transfer the control to the caller, then we print the value in the caller until we get the ready state of the future in the caller. Is this a typical way to implement the yield function by using await in rust? In other words, can we implement the complete function of yield only by using await?

"Is it a typical way" and "can we" are two very different questions.

Typical? Absolutely not. In Rust, one would typically implement and use an Iterator for iteration.

But can you do this? Well, if the code above compiles and runs as you expected, then it's a constructive proof that you can.

1 Like

Are you looking for something like this?

1 Like

It just works the same way as I expected. Rust Playground, I just wonder to confirm whether await is sufficient to be used to implement all functions brought by yield?

Seems like that crate uses the same idea as what I'm saying here?

Technically, yes, but in practice you would want something like this to be built into the compiler. That way you get good type inference and are less likely to hit unreadable compile errors.

It also lets the compiler generate better types and we aren't trying to shoe-horn a generator shaped peg into a Future shaped hole.

1 Like