6 ms·
Author here. I hear what you're saying. But there's lots of times while using rust where the language supports feature X and feature Y, but the features can't b
by josephg 2y ago
Author here. I hear what you're saying. But there's lots of times while using rust where the language supports feature X and feature Y, but the features can't be used together.
For example, you can write functions which return an impl Trait. And structs can contain arbitrary fields. But you can't write a struct which contains a value returned via impl Trait - because you can't name the type.
Or, I can write if a && b. And I can write if let Some(x) = x. But I can't combine those features together to write if let Some(x) = x && b.
I want things like this to be fixed. Do I want rust to be "bigger"? I mean, measured by the number of lines in the compiler, probably yeah? But measured from the point of view of "how complex is rust to learn and use", feature holes make the language more complex. Fixing these problems would make the language simpler to learn and simpler to use, because developers don't have to remember as much stuff. You can just program the obvious way.
Pin didn't take much work to implement in the standard library. But its not a "lean" feature. It takes a massive cognitive burden to use - to say nothing of how complex code that uses it becomes. I'd rather clean, simple, easy to read rust code and a complex borrow checker than a simple compiler and hard to use language.
- valenterry 2y agoYeah, I agree wholeheartedly with that. This is also what I really dislike in many languages. You should have a look at Scala 3. Not saying that I'm perfectly happy with the direction of the language - but Scala really got those foundations well and made it so that it has few features but they are very powerful and can be combined very well. Rust took a lot of inspiration from Scala for a reason - but then Rust wants to achieve zero-cost abstraction and do high-performance, so it has to make compromises accordingly for good reasons. Some of those compromises affect the ergonomics of the language unfortunately.
- gary17the 2y agoI think it would be helpful to clearly distinguish between PL simplification (e.g., "if let Some(x) = x, x == 42 {}") and convenience-driven PL expansion (e.g., "let @discardable lhs = rhs ?? 0;"). In case of the former, I'm with you. In case of the latter, I'm not. Rust likely isn't meant to be a tool that is easy to learn at all costs (since the borrow checker does exist, after all). Rust is, IMvHO, supposed to be like vi: hard to learn and easy to use :).
- adastra22 2y agoWe should strive for easy to learn, easy to use.
- Measter 2y agoThough we should also accept that some things are just hard. Though that's not to say that we should give up on trying to make them as easy to learn and use as possible.
- adastra22 2y agoI don’t know. This certainly isn’t provable. What’s the difference between a something being intrinsically difficult and something for which adequate UI just hasn’t been figured out yet? I don’t know anything that hasn’t been made simpler and easier over time.
- FridgeSeal 2y agoSome things have inherent complexity. Different formulations or UX can alleviate some of this complexity, but often it is shifted around, or hidden - not actually solved. Some solutions can definitely make a situation net-worse/net-more-complex, and occasionally we get advances in theory which can change the watermark on complexity, but it never _goes away_.
- 3np 2y ago> I don’t know anything that hasn’t been made simpler and easier over time. Ever implemented a cyclic linked list or graph in Rust?
- withoutboats3 2y agoThese features are slow to be accepted for good reasons, not just out of some sort of pique. For example, the design space around combining `if let` pattern matching with boolean expressions has a lot of fraught issues around the scoping of the bindings declared in the pattern. This becomes especially complex when you consider the `||` operator. The obvious examples you want to use work fine, but the feature needs to be designed in such a way that the language remains internally consistent and works in all edge cases. > Pin didn't take much work to implement in the standard library. But its not a "lean" feature. It takes a massive cognitive burden to use - to say nothing of how complex code that uses it becomes. I'd rather clean, simple, easy to read rust code and a complex borrow checker than a simple compiler and a horrible language. Your commentary on Pin in this post is even more sophomoric than the rest of it and mostly either wrong or off the point. I find this quite frustrating, especially since I wrote detailed posts explaining Pin and its development just a few months ago. https://without.boats/blog/pin/ https://without.boats/blog/pin/ https://without.boats/blog/pinned-places/ https://without.boats/blog/pinned-places/
- adwn 2y ago> Your commentary on Pin in this post is even more sophomoric than the rest of it and mostly either wrong or off the point. I find this quite frustrating, especially since I wrote detailed posts explaining Pin and its development just a few months ago. To me, this sounds as if the Pin concept is so difficult to understand that it's hard to even formulate correct criticism about it. I get that Pin serves a critical need related to generators and async, and in that it was a stroke of genius. But you as the creator of Pin might not be the right person to judge how difficult Pin is for the more average developers among us.
- withoutboats3 2y agoIf you actually read my posts you would see that I acknowledge and analyze the difficulty with using Pin and propose a solution which makes it much easier to deal with. My understanding is that the Rust project is now pursuing a solution along the lines of what I suggested in these posts.
- 2y ago
- devit 2y agoYou can make the struct generic on the type to have a field being an impl Trait type.
- josephg 2y agoI know. Sometimes that can work. But that choice will ripple out to cause all sorts of other complications throughout your codebase. Now you have a Struct<T>. How do you pass one of these structs as a parameter to another function? Do you need to make that function generic over all T? How do you embed that into another struct, in turn? Do you put generic arguments everywhere? And so on. Fundamentally, I don't want my type to be generic over all implementations. I want a concrete type. I want the type returned by one specific, often private, function. But, nope. Not today. Maybe with TAIT, whenever that ships.
- FridgeSeal 2y agoAm I right in understanding: you want some private, internal structure to be generic over some types, but you don’t want any wrapping structs to carry around that generic? Could this problem be reformulated to use associated types, rather than full generics?
- josephg 2y agoNo. I have a function which returns impl Trait. The most common culprit for this is impl Iterator. (For example, a function does a map, filter or fold over something else and returns the resulting iterator). I want to make another struct which slowly consumes that impl Iterator. So, the second struct is struct MyStruct { iter: (iterator returned from that function above) }. Unfortunately, the iterator type doesn’t have a name. So currently that means it’s impossible to put this iterator in a struct. This makes anything returned via impl Iterator (and impl Future and so on) second class citizens in rust. You are very limited in the ways you can use these objects compared to normal values. My code is filled with hand written iterators that I could construct much more easily with map/filter/fold and friends. But I make them the long way simply so the resulting type has a name. The current situation is very silly.
- nindalf 2y agoIt is easier to make big breaking changes when there are fewer users, for sure. I think what you ignore is both the progress that is being made and how difficult it is to make that progress while maintaining a stable language that works for all the existing users. I'll give an example - async traits. On the surface it seems fairly simple to add? I can say async fn, but for the longest time I couldn't say async fn inside a trait? It took years of work to solve all the thorny issues blocking this in a stable, backwards compatible way and finally ship it [1]. There is still more work to be done but the good news is that they're making good progress here! You pointed out one feature that Rust in Linux needs (no panics), but there are several more [2]. That list looks vast, because it is. It represents years of work completed and several more years of work in the Rust and Rust for Linux projects. It might seem reasonable to ask why we can't have it right now, but like Linus said recently "getting kernel Rust up to production levels will happen, but it will take years". [3] He also pointed out that the project to build Linux with clang took 10 years, so slow progress shouldn't discourage folks. The important thing is that the Rust project maintainers have publicly committed to working on it right now - "For 2024H2 we will work to close the largest gaps that block support (for adopting Rust in the kernel)". [4] You dream of a language that could make bold breaking changes and mention Python 2.7 in passing. The Python 2/3 split was immensely painful and widely considered to be a mistake, even among the people who had advocated for it. The Rust project has a better mechanism for small, opt-in, breaking changes - the Edition system. That has worked well for the last 9 years and has led to tremendous adoption - more than doubling every year [5]. IMO there's no reason to fix what isn't broken. I guess what I'm saying is, patience is the key here. Each release might not bring much because it only represents 6 weeks of work, but the cumulative effect of a year's worth of changes is pretty fantastic. Keep the faith. [1] - https://blog.rust-lang.org/2023/12/21/async-fn-rpit-in-traits.html https://blog.rust-lang.org/2023/12/21/async-fn-rpit-in-trait... [2] - https://github.com/Rust-for-Linux/linux/issues/2 https://github.com/Rust-for-Linux/linux/issues/2 [3] - https://lwn.net/SubscriberLink/991062/b0df468b40b21f5d/ https://lwn.net/SubscriberLink/991062/b0df468b40b21f5d/ [4] - https://blog.rust-lang.org/2024/08/12/Project-goals.html https://blog.rust-lang.org/2024/08/12/Project-goals.html [5] - https://lib.rs/stats https://lib.rs/stats
- cdaringe 2y agoDude YES. This stuff was maddening in rust. “How many links to GitHub issues will the compiler fire at me today” was a sincere feeling. I think it’s much better these days, but you still get em doing async work
- pdimitar 2y agoI hate it as well and I also feel async Rust needs years of much better love than it received at its conception. But... some info is still better than no info.