7 ms·
A bunch of things you don't like about Rust? Turns out that the person who originally created the language doesn't like them either. I know that the main point
by jstx1 3y ago
A bunch of things you don't like about Rust? Turns out that the person who originally created the language doesn't like them either.
I know that the main point is about governance and how having a BDFL would have led to a completely different language but I really would have preferred the Graydon-BDFL-Rust to what we have today.
Very interesting article, worth a read.
- elcritch 3y agoOne highlight from the article: > Traits. I generally don't like traits / typeclasses. To my eyes they're too type-directed, too global, too much like programming and debugging a distributed set of invisible inference rules, and produce too much coupling between libraries in terms of what is or isn't allowed to maintain coherence. Very much this! > I wanted (and got part way into building) a first class module system in the ML tradition. Many team members objected because these systems are more verbose, often painfully so, and I lost the argument. But I still don't like the result, and I would probably have backed the experiment out "if I'd been BDFL". I seen this the ML first class module system mentioned in a few different contexts and want to pick it up at some point.
- wuiheerfoj 3y agoMay I ask what you don’t like about traits (and perhaps insight on what the author meant)? Being a relative rust noob compared to other languages, I always felt traits were a super power when compared to eg interfaces in Java/C++ and flexible but with useful constraints compared to the structural typing nature of Typescript interfaces
- nyanpasu64 3y agoImporting a trait into scope can silently materialize methods on other types, with no syntax at the method call site pointing to which import statement created the methods, requiring you to ask the compiler/IDE. This can also mean that removing a use statement with no references to the type being used in the entire rest of the source file, can make code suddenly stop compiling. I've worked around this by strictly confining "specialized" traits (like std::io::Write or std::fmt::Write, why are there two Writes?!) to the beginning of a single function, but I'm lazy and put "general" traits like std::borrow::Borrow and std::str::FromStr at the top of my file. Which types grow new trait methods is dependent on trait implementations, which can be generic and apply to an unbounded number of types, based on complex matching rules, and figuring out requires reading every impl of that trait to see if any match a given type, or asking the compiler/IDE. I want to explore languages which explicitly select a trait implementation at the call site (like a Heap<int, int_greater> type which uses int_greater::cmp() to implement a min/max heap), or naming the trait (but not picking an impl) at the trait method call site (like Write::write_all(stream, "hello world") or (stream as Write).write_all("hello world")). I think Zig takes a similar direction.
- zozbot234 3y agoYou can use universal function call syntax in Rust: <Type<TyArg> as Trait>::trait_fn(self_arg, fn_arg1, fn_arg2);
- glandium 3y agoThere's worse. When your trait adds function foo and your code does obj.foo(), if the underlying type later adds a foo method, compilation breaks. This is very common with traits that usefully add useful methods that are missing in libstd... which break when said method is finally added there.
- Gwypaas 3y agoI ran into this case yesterday, for some cases there are warnings now. In this case I used ".div_ceil(...)" from from the Num [0] crate. (some_integer).div_ceil(&2) ^^^^^^^^ = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior! = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919> = help: call with fully qualified syntax `num::Integer::div_ceil(...)` to keep using the current method = note: `#[warn(unstable_name_collisions)]` on by default [0]: https://crates.io/crates/num https://crates.io/crates/num
- sanxiyn 3y agoIn a trait-like system (including Java interface), there can be only one implementation of a trait for a type. That's why it is global, unlike ML module-like systems. Global is another word for anti-modular. For example, in the real world, there are multiple ways to order strings (called collation), but since there can be only one implementation of (String, Ord) type-trait pair, one ordering is canonical. That may be bearable, but having canonical (String, Hash) implementation is not. What if you want to use (say) faster CityHash instead of canonical MurmurHash? So Rust resorts to things like BuildHasher, to get back multiple implementations. Because it is global/anti-modular, it interferes with separate compilation, and it is one of reasons why Rust is slow to compile. Then why would one use trait instead of module? Since there can be multiple implementations in module, you need to specify. So module is more verbose. In my (and Graydon's) opinion, a bit more verbosity is worth it for modularity, but many people disagreed. This is another theme: Graydon is okay with verbosity, boilerplate, and being bureaucratic. In my (and Graydon's) opinion, programming is work that is secretarial, not artistic, so it is unimportant whether code is ugly or not. You may think current Rust is ugly, but no, it is the way it is because lots of people really cared about Rust code being pretty. If Graydon was a BDFL, Rust would be even more ugly, and in my opinion, as a result, would be a better programming language.
- wuiheerfoj 3y agoThanks for this - the sort example made a lot of sense to me. I thought it was possible to parameterise with specific trait implementations for such a case though I haven’t used it much with I could be misunderstanding.
- giraffe_lady 3y agoI loved reading that part! I've always found ocaml's (and now rescript's) first class modules flexible and powerful. They're definitely awkward but in that way where you're having to explicitly think about and declare relationships you'd happily ignore until they bite you. Recently I've seen a lot of programmers I respect consider them a weaker or failed alternative to typeclasses, basically a dead-end. And I had been reluctantly coming to the conclusion that I must be wrong in some way I'm not able to fully perceive yet. Seeing such a notable PL designer come out on their side makes me feel less like a fool.
- dan-robertson 3y agoI often felt that being canonical was a pretty big advantage of traits. For example if you use first-class modules then every time you want a sort or a binary search tree you need to specify the choice of comparison operator for the elements. And a data structure for a search tree must somehow encode this in the type system so eg you can’t merge two trees with the same key type but different comparison functions. The most obvious way to implement this causes problems for other cases like writing functions generic in the types of keys/values (else you get extremely verbose code). Canonical instances goes against modularity but something like modular implicits for ML-family languages could improve the terse was a lot to something closer to Haskell levels. You still miss out on the other advantage rust has: the dot operator is great because it allows identifiers to contain less context (they don’t need to have long global names or be hidden away in some tree of modules: you can have .map mean different things for different types) and gives a massive hint to autocomplete for which things to suggest (I don’t know how you even signal to autocomplete in a language like ML that you would like a function to operate on the following value so please suggest things with the right type).
- zozbot234 3y agoMost type systems are not full-featured enough to elegantly encode traits/typeclasses or ML modules. You need dependent types, as seen in languages like Agda or Idris. And these in turn are hard to implement in a language with a traditional compile/run phase distinction like Rust: the _full_ feature-set of dependent types is pretty much only available at compile time. (Which is why dependent-typed languages tend to add "program extraction" features, which reintroduce that phase separation in a rather ad-hoc way.)
- eru 3y agoHaving used both OCaml and Haskell in production, I can say that the typeclass way of doing things is massively more convenient. But I guess enough syntactic sugar might make things palatable.
- skellington 3y agoCommittees tend to design less beautiful things. Look at modern c++ too. What a mess. Everyone in the committee has to jam in their favorite feature, much of which is sugar.
- nsajko 3y agoModern C++ is actually going relatively OK? You may be thinking of the old, pre-C++11 C++?
- chippiewill 3y agoModern C++ _is_ actually a mess to be fair. Overall it's still an improvement on pre-c++11, but when looking at it end-to-end it feels awfully disjointed.
- Sankozi 3y agoIf you have a mess and add something to it, you still have a mess, probably a bigger one. To clean the mess you need to remove something (which is really hard in a programming language) not to add something. Selecting and enforcing usage of a subset of C++ is a way to deal with that mess which companies frequently use.
- zozbot234 3y ago> To clean the mess you need to remove something Sure, but that's why Carbon and Cppfront are a thing now. These two actively remove stuff from C++. We'll probably see this happen in the Rust community as well once the newer Crab language becomes established. Then we'll have to rewrite everything in Crab, but it will probably be a lot simpler than the Rust rewrite.
- deleted 3y ago[deleted]
- nsajko 3y agoEverything is a mess. The universe is a mess. That doesn't make perfectionism a good thing. Besides, the C++ committee does, in fact, remove stuff from the language to clean the mess, just not without due care.
- rtpg 3y agoI am very glad to not have Rust end up along that path (I am sympathetic to the threading idea he mentioned though). Rust as an alternative to C++ does, for me, involve all of the weird magical nonsense that you kind of need to get any of this working. The extreme use of generics to build out DSLs to get things working. General libraries being very hard to write, but still possible, to get alright ergonomics for usage itself. And yeah... the zero-cost abstraction thing. I think Graydon-Rust would have also been very interesting, but it sounds unappealing to me, person who wants "C++ but nicer". But to his point... saying "you could have much faster compile times" is very tempting! Just, especially when it's messing around with Rust "for fun", the ergonomics sound pretty unfun.
- xiphias2 3y agoSome Rust developer said that Rust was originally what Go has become. So if you want to try something like that, just look at Go :)
- hajile 3y agoGo is actually a competitor with StandardML and loses badly in every way except having Google's deep pockets to carry it. StandardML uses a far superior Hindley-Milner type system. It has pattern matching. It has Option types for good error handling. It doesn't have bad features (for GC'd languages) like direct pointers and slices. It has immutability by default. CML even offers a better take on channels too. Modules keep interfaces more standardized (superior for big projects IMO). And to top it all off, SML is easier to learn than Go. It's also as fast as Go (despite the compilers being a side project). Go's only advantage is more extensive libraries, but that would be fixable in SML with just a fraction of the money Google spent on Go.
- gautamcgoel 3y agoThis all makes sense to me, but can you explain why it is a bad idea to have slices in a GC'd language?
- crispinb 3y ago> Turns out that the person who originally created the language doesn't like them either. But it also turns out the very same isn't as neurotically attached to his 'likes' as most of us are: > The Rust I Wanted probably had no future, or at least not one anywhere near as good as The Rust We Got. The fact that there was any path that achieved the level of success the language has seen so far is frankly miraculous. Don't jinx it by imagining I would have done any better! He understands that his likes are just contingent facts about a single mammal, not truths. This is a hard-won understanding. Most people never reach it.
- shoulderfake 3y ago[dead]
- avgcorrection 3y ago> A bunch of things you don't like about Rust? Turns out that the person who originally created the language doesn't like them either. Yep. That just goes to show that you shouldn’t put individuals on pedestals as if they are superheroes. More things than we usually think are in fact team efforts. > I know that the main point is about governance and how having a BDFL would have led to a completely different language That isn’t the only main point. > > The Rust I Wanted probably had no future, or at least not one anywhere near as good as The Rust We Got. If you would be fine with a niche language then that “Rust” would have worked for you. But if you also wanted a language with wide industry backin etc.—maybe not so much.
- lamontcg 3y agoI think I mostly want a language like Graydon-Rust, but not with the Expressivity tradeoff (or at least not as hardcore as it sounds like Graydon is).