Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> I'm not sure what's neutered about Rust's current plans for generators

They're neutered because they can't suspend and transfer control to a function other than the one that called them ("Note also that "coroutines" here are really "semicoroutines" since they can only yield back to their caller." https://lang-team.rust-lang.org/design_notes/general_corouti...) and you can't pass values into resume and get them out from the yield statement in the coroutine (https://github.com/rust-lang/rust/issues/43122#issuecomment-...).

> and they aren't separate from async, they're the foundation that async desugars to.

Yeah I just looked it up again and I don't know why I had it in my head that they were separate, you're correct, they are the same thing under the hood, so honestly that eliminates my biggest problem with them.

> 'm also not sure what your objection is to Polonius, which, so far, is still just a strictly more permissive version of the borrow checker, with nothing new to learn on the user end.

The entire model is different under the hood, though, since it switches from lifetimes+borrows to loans, and so in order to fully understand its behavior the user really would have to change their mental model, and as I said above I'm a huge fan of the lifetimes model and less so of the loan model. I just feel like it's much more natural to treat the ownership of a memory object and therefore amount of time in your code that object lives as the fixed point, and borrows as wrong for outliving what they refer to, then to treat borrows as the fixed point, and objects as wrong for going out of scope and being dropped before the borrow ends, because the fundamental memory management model of Rust is single ownership of objects, moves, and scope based RAII via Drop, so the lifetime of an object kind of is the more basic building block of the memory model, with borrows sort of conceptually orbiting around that and naturally being adjusted to fit that, with the checker being a way to force you to adhere to that. The loan based way of thinking would make more sense for an ARC-based language where references actually are more basic because objects really do only live for as long as there are references to them.



> you can't pass values into resume and get them out from the yield statement in the coroutine

I think that the linked comment is out of date, and that this is supported now (hard to tell because it hasn't been close enough to stabilization to be properly documented): https://github.com/rust-lang/rust/pull/68524

As for Polonius changing the underlying mental model, I think this is a natural progression. Rust 1.0 tried to present a simple lexical model of borrowing, and then enough people complained that it has long since replaced the simple model with non-lexical lifetimes in order to trade simplicity for "do what I mean". And since it's not allowed to break any old code, if you want to continue treating borrowing like it has the previous model then that shouldn't present any difficulties.


> They're neutered because they can't suspend and transfer control to a function other than the one that called them ("Note also that "coroutines" here are really "semicoroutines" since they can only yield back to their caller." https://lang-team.rust-lang.org/design_notes/general_corouti...)

Huh? At first glance wanting to do this sounds absolutely insane to me. As in, it sounds a lot like "imagine a function could return not just to its caller function, but to other functions as well! So if you call it, it might be that you won't even end up returning to the same function with which you started, but somewhere completely different".

What am I missing? This sounds absolutely insane at first glance, like a straight-up go-to. What's the most simple use case for these sort of weird yields to other functions?


That's the essence of co-routines vs. sub-routines. If you've ever used a Unix pipe you've used a limited form of coroutines. "ps | grep foo" tells process A, the shell, to fire up processes B (ps) and C (grep), and tells B to send results to C, not its caller A. B runs a bit and yields, returning some data via stdout. C runs a bit, reading the result via stdin, then yields to B and waits for B to return more data. Pipes are actually bidirectional, so its possible for C to send results to B when it yields, but off the top of my head I can't think of a real such example.


I suppose conceptually they're similar but you're oversimplifying how Unix pipes work to the extent that it's apples to oranges in comparison to async/coroutines.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: