9 ms·
Why did polling have to be baked into the language? Seems bizarre for a supposedly portable language to assume the functionality of an OS feature which could ch
by zelly 6y ago
Why did polling have to be baked into the language? Seems bizarre for a supposedly portable language to assume the functionality of an OS feature which could change in the future.
Meanwhile C and C++ can easily adopt any async system call style because it made no assumptions in the standards about how that would be done.
Rust also didn't solve the colored functions problem. Most people think that's an impossible problem to solve without a VM/runtime (like Java Loom), but people also thought garbage collection was impossible in a systems language until Rust solved it. It could have been a great opportunity for them.
- newpavlov 6y ago>Why did polling have to be baked into the language? See this comment: https://news.ycombinator.com/item?id=26407440 https://news.ycombinator.com/item?id=26407440 >Meanwhile C and C++ can easily adopt any async system call style because it made no assumptions in the standards about how that would be done. Do you know about co_await in C++20? AFAIK (I only have a very cursory knowledge about it, so I may be wrong) it also makes some trade-offs, e.g. it requires allocations, while in Rust async tasks can live on stack or statically allocated regions of memory. Also do not forget that Rust has to ensure memory safety at compile time, while C++ can be much more relaxed about it.
- zelly 6y agoC++20 coroutines are not async in the standard. They are just coroutines. Actually they have no implementation. The user has to write classes to implement the promise type and the awaitable type. You could just as easily write a coroutine library wrapping epoll as you could io_uring. The only thing it does behind your back (other than compile to stackless coroutines) is allocate memory, which also goes for a lot of other things.
- saurik 6y agoIs this not also true of Rust? Are you saying Rust in some sense hardcodes an implementation to await in a way C++ doesn't? (I am not a Rust programmer, but I am very very curious about this and would appreciate any insight; I do program in C++ with co_await daily, with my own promise/task classes.)
- kibwen 6y agoRust's async/await support is not intended as a general replacement of coroutines. In fact, async/await is built on top of coroutines (what Rust calls "generators"), but these are not yet stable. https://github.com/rust-lang/rust/issues/43122 https://github.com/rust-lang/rust/issues/43122
- saurik 6y agoOuch... thanks; I didn't realize the Rust situation was this bad :(. FWIW, I do not look at generators as being what I would want as my interface for working with coroutines, and am very much on board there with the comments from tommythorn. I guess I just have too many decades of experience working with coroutines in various systems I have used :(. https://github.com/rust-lang/rust/issues/43122#issuecomment-716256938 https://github.com/rust-lang/rust/issues/43122#issuecomment-... https://github.com/rust-lang/rust/issues/43122#issuecomment-716265969 https://github.com/rust-lang/rust/issues/43122#issuecomment-...
- steveklabnik 6y agoYou may want to watch/read my talk: https://www.infoq.com/presentations/rust-2019/ https://www.infoq.com/presentations/rust-2019/ I also did a follow up, walking through how you would implement all of the bits: https://www.infoq.com/presentations/rust-async-await/ https://www.infoq.com/presentations/rust-async-await/ TL;DR: rust makes you bring some sort of executor along. You can write your own, you can use someone else's. I have not done enough of a deep dive into what made it into the standard to give you a great line-by-line comparison.
- pjmlp 6y agoWhich makes them quite powerful, as they allow for other kinds of patterns.
- mratsim 6y agoIt requires allocation if the coroutine outlives the scope that created it. Otherwise compiler are free to implement heap allocation elision (which is done in Clang). Now compared to Rust, assuming you have a series of coroutines to process a deferred event, Rust will allocate once for the whole series while C++ would allocate once per coroutine to store them in the reactor/proactor.
- steveklabnik 6y agoRust never implicitly allocates, even with async/await. I have written Rust programs on a microcontroller with no heap, using async/await for it.
- mratsim 6y agoI don't think I've implied that allocation in Rust was implicit but that's a fair point.
- steveklabnik 6y agoYou said > Rust will allocate once for the whole series which, it will not. It is true that some executors will do a single allocation for the whole series, but that is not done by Rust, nor is required. That's all!
- ilammy 6y ago> people also thought garbage collection was impossible in a systems language until Rust solved it Only if you understand "garbage collection" in a narrow sense of memory safety, no explicit free() calls, a relatively readable syntax for passing objects around, and acceptable amount of unused memory. This comes with a non-negligible amount of small text for Rust when compared to garbage-collected languages.
- moonchild 6y ago> people also thought garbage collection was impossible in a systems language until Rust solved it No, they didn't. Linear typing for systems languages had already been done in ats, cyclone, and clean, the latter two of which were a major inspiration for rust. Venturing further into gc territory: long before rust was even a twinkle in graydon hoare's eye, smart pointers were happening in c++, and apple was experimenting with objective c for drivers.
- pjmlp 6y agoApple wasn't experimenting with Objective-C for drivers, NeXTSTEP drivers were written in Objective-C. macOS IO Kit replacement, Driver Kit, is an homage to NeXTSTEP Driver Kit name, the Objective-C framework.
- roca 6y agoPerhaps more accurate to say "safe reclamation of dynamic allocations without GC was not known to be possible in a practical programming language, before Rust". The problem with languages like ATS and Cyclone is that you need heavy usage in real-world applications to prove that your approach is actually usable by developers at scale. Rust achieved that first.
- benibela 6y agoI have always thought Pascal solved that in practise with automated reference counting on arrays A good optimizer could then have removed the counting on non-escaping local variables
- steveklabnik 6y agoIf you squint, this is sorta what Swift is.
- moonchild 6y agoCyclone was a c derivative (I believe it was even backwards compatible), and ats a blend of ml and c. Ml and c are both certainly proven. Cyclone was, and ats is, a research project; not necessarily intended to achieve widespread use. And again, obj-c was being used by apple in drivers, which is certainly a real-world application. > without GC I don't know what you mean by this. GC is a memory management policy in which the programmer does not need to manually end the lifetimes of objects. Rust is a garbage collected language. How many manual calls to 'drop' or 'free' does the average rust program have?
- pjmlp 6y ago> but people also thought garbage collection was impossible in a systems language until Rust solved it? What? Several OSes have proven their value written in GC enabled systems programming languages. They aren't as mainstream as they should due to UNIX cargo cult and anti-GC Luddites. Rust only proved that affine types can be easier than cyclone and ATS.
- kibwen 6y ago> Meanwhile C and C++ can easily adopt any async system call style because it made no assumptions in the standards about how that would be done. This is comparing apples to oranges; Rust's general, no-assumptions-baked-in coroutines feature is called "generators", and are not yet stable. It is this feature that is internally used to implement async/await. https://github.com/rust-lang/rust/issues/43122 https://github.com/rust-lang/rust/issues/43122