34 ms·
The Rust I wanted had no future
- jstx1 3y agoA 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).
- sph 3y agoVery interesting insight from Graydon, in hindsight I too would have loved something more towards ML than C++. I never liked the kitchen sink approach that I see first C++, now Rust moving towards, but I respect what Rust has managed to solidify into. It's a good language. That said, I still hate async with a passion, it makes the language more complex and not very elegant (i.e. function coloring). And now that I know how it works behind the scene (thanks to Jon Gjengset [1]), it feels so complicated and hacky, a mediocre very high level concept that someone managed to implement as a zero-cost abstraction. Impressive, but still a bad idea. I'm sure the pro of having a BDFL instead of a committee is being able to follow a singular vision, instead of trying to appease members by adding the fad du jour which might stray a little too far from the original vision. Too many chefs in the kitchen and all. 1: https://www.youtube.com/watch?v=ThjvMReOXYM https://www.youtube.com/watch?v=ThjvMReOXYM
- TurboHaskal 3y ago> I too would have loved something more towards ML than C++ I stopped paying attention to the language around 2012-2013 or so when the direction clearly steered towards the latter. You may want to check https://austral-lang.org/ https://austral-lang.org/ out.
- dorian-graph 3y agoI was about to ask if there's any "Rust by ML" languages out there. Thank you.
- noelwelsh 3y agoO'Caml is heading in that direction. Jane Street are adding more control over memory layout and allocation, and multicore finally arrived recently.
- gautamcgoel 3y agoLol there's no apostrophe in OCaml - it's not an Irish name like, say, O'Brian.
- moonchrome 3y agoAs someone casually following Rust and haven't touched it or C++ in probably 5+ years (but keeping tabs in hope of coming back to that world), I feel like a lot of decisions he mentions are what made me optimistic about Rust adoption/positioning itself as a modern C++ replacement. So I kind of agree with his conclusion - his version of Rust would be much less interesting to me, and I think a lot of it's current users. eg. I only started playing with Rust once they removed green threads. Zero cost abstractions are a major selling point.
- kzrdude 3y agoI was at the sidelines when Rust 1.0 was being made and I think it got into an llvm induced feedback loop. Slowly turning into C or C++ with other features but the same type, object and memory model. Part of the reason was Rust's desire to show itself as a direct competitor w.r.t performance, I think.
- Ygg2 3y agoPerformance, but with sanity. Say you use a vector in C++. You push one element and pop two. In Rust that's a None. In C++ the answer is UB (in my case 43).
- intelVISA 3y agoThe fatal mistake here is using the STL...
- tialaramex 3y agoThe safe thing Rust did here is affordable in Rust (Option<T> is the same size as T for many T including all references) so they could afford to do it, whereas it's expensive in C++. Could it have been made cheaper in C++? Sure, but safety wasn't their priority so who cares? That prioritisation applies to the whole ISO language, not only to the standard library.
- 3y ago
- Aissen 3y agoOn integer wrapping, I think explicit wrap is annoying at first, but eliminates a whole class of bug. I can only agree with: > (Swift at least traps in release by default -- I wish Rust had chosen to). I enable it in release on serious projects: [profile.release] overflow-checks = true
- wongarsu 3y agoAt least Rust has left the door open to allow panicking on overflow even in release builds in the future - presumably on platforms where hardware support makes this cheap enough.
- layer8 3y agoThe correct (but hard) way to prevent overflow-related bugs would be to insist on the compiler being able to prove that no overflow can occur. Basically the same thing you do in your head to convince yourself that the program is correct and won’t overflow, only in a more formally rigorous fashion. Modulo semantics by itself doesn’t prevent bugs.
- the_duke 3y agoRust has an optional clippy lint that will warn/forbid all basic arithmetic that might over/underflow, forcing you to use dedicated methods with explicit behaviour instead. It's very annoying , but I use it in code where this is critical.
- jedisct1 3y agoAnd then you may just have introduced side channels in crypto code.
- Aissen 3y ago> And then you may just have introduced side channels in crypto code. incorrect crypto code. If overflow is intentional, it should be annotated as such in operations, will generate similar assembly and won't panic. If it isn't intentional, then the code was bad to begin with.
- Keyframe 3y agoThe Rust he wanted sounds a lot like Ada.
- tejinderss 3y agoOr like ocaml with its module system and no explicit lifetimes / & type.
- glandium 3y agoThe original rust compiler was written in ... Ocaml.
- lawn 3y agoWhich reminds me, I really need to try out ocaml.
- giraffe_lady 3y agoA really unknown and underrated language for how good it is right now is rescript. It's ocaml's type & module systems and runtime semantics grafted onto JS. Ocaml's tooling, ecosystem, and standard lib situation are all ...fine... but quirky in ways that can be barriers when learning it. Rescript lets you skip most of those, plus the (overblown but also real) weird syntax. I like ocaml and use it for projects still but if you just want to play around with what's unique and strong about it, rescript is what I would recommend right now.
- erik_seaberg 3y agoI’m very glad expressivity won out. I would like our profession to stop accepting tools that waste effort. I’ve always seen safety and lifetimes and borrowing as the main value prop, so I was surprised to see he was sort of aiming at an ML without GC, rather than a C++ that doesn’t blow up.
- dan-robertson 3y agoEarly rust did have gc so it was more of an ML with optional gc, and maybe a dot operator. (And no closures apparently)
- mhd 3y agoAh, Sather gets mentioned. That's a name I haven't heard in a long time. I remember looking at it during the latter half of the 90s when I was searching for the perfect OO language... https://www1.icsi.berkeley.edu/~sather/ https://www1.icsi.berkeley.edu/~sather/
- tech2 3y agoSather was something I was first exposed to at university in the mid 90s, and I still have a lot of respect for its looping mechanism. Code inclusion in classes rather than inheritance was also pretty cool. Pre/post conditions, invariants. I miss a lot of it. I recently revisited it for Advent of Code (where part of the challenge was getting the compiler itself to even build with even semi-modern tooling), and a lot of the above features still have value.
- TowerTall 3y agoThe article starts with "In a recent podcast about Rust leadership, the BDFL question came up again" What it BDFL?
- Fiahil 3y agoBenevolent dictator for life. "Benevolent dictator for life (BDFL) is a title given to a small number of open-source software development leaders, typically project founders who retain the final say in disputes or arguments within the community. The phrase originated in 1995 with reference to Guido van Rossum, creator of the Python programming language."
- TowerTall 3y agoInteresting. Isn't a BDFL needed in Open Source projects (not talking specific about Rust, but Open Source in general)? I work in a commercial software company. We have a CTO and he retain the final say in disputes or arguments. He also steers the global technical direction we take the software and has the final say, but he can get fired. Is that the main difference between a CTO and a BDFL? What alternatives are there?
- sanxiyn 3y agoThe usual alternative is a committee, see for example Apache Software Foundation's Project Management Committee Guide: https://www.apache.org/dev/pmc.html https://www.apache.org/dev/pmc.html
- pm215 3y agoI suspect an informal grouping (i.e. more long-standing/senior contributors with default control over some parts of the codebase and operating by informal consensus between themselves) is probably at least as common (maybe more so) than an officially named committee with rules of procedure.
- zozbot234 3y agoThe main difference between a CTO and a BDFL is that if you disagree with a BDFL, you can just fork the project under a new name. This right to fork is key to making FLOSS development work. If you disagree with a CTO, there isn't much that you can do besides buying up the whole company (see Elon Musk and TWTR as an example).
- zozbot234 3y agoTechnically, Rust had no future prior to the 2018 edition. The fact that Rust can add new features as the use cases for it evolve is a strength of the language, one that it had from the start even with Graydon as a BDFL.
- LeanderK 3y agoCan someone comment on "Library-defined containers, iteration and smart pointers"? I have no rust experience so far. Magic compiler support for such primitives is something I usually very much, really strongly dislike, it was always my experience that it is the wrong point of abstraction because it just reduces the design state so much. But then you need good support for inlining the relevant parts of the language, which I think is very often very poorly done. In fact, I have so far never seen a solution I like. What is the rust experience wrt to inlining? Can every expression be inlined or only selected ones? How can you know what got inlined in some expression? Do you have to manually annotate every single function call you have to inline or is there a more general command?
- tijsvd 3y agoEverything that's visible to the compiler is subject to automatic inlining. That is all code in the current crate (compilation unit), all concrete instantiations of generics (regardless where defined), and all functions marked inline (regardless which crate). Stdlib containers are all in the generics category.
- LeanderK 3y ago> all functions marked inline (regardless which crate). Is this a problem is rust? Is too much/too little marked inline? What if you really need to inline some function from some library that was not marked inline by the author?
- JonChesterfield 3y agoIf containers, control flow and so forth are expressible as library code you get a simpler compiler and stuff determined users can reasonably debug, modify, replace. It means you have to improve the core language enough to implement them and/or have magic compiler intrinsics which are only intended for use by that library. If you implement these things in the compiler (open code means emit the implementation inline as you go, can also emit calls to the compiler runtime which is roughly similar to library code that the compiler ships and knows lots about) then users need to hack the compiler to change them. However, if the structures are in the compiler, and you've done things like encode them directly in the AST, the compiler has a better chance of emitting useful diagnostics for them and of optimising them at the semantic level of the container. C++ goes with library code supported by compiler intrinsics, and a common developer experience is compilation errors referring to iterators some distance into the library code. It also can't sanely do things like call reserve on a vector outside of a loop, because by the time it's ready to optimise things it's holding raw pointers with mangled names, not a hashmap instance. Conventional wisdom is to put containers in the stdlib. D has some support in the compiler. I'm starting to think this is one where conventional wisdom has got it wrong.
- PhilipRoman 3y agoHaven't followed Rust too much, but I'm always surprised when I hear that Rust is too difficult or not ergonomic. As I understand it is meant to be a systems level language; something you'd use to write kernels, TCP stacks, browsers and ssh daemons. Anyone writing these things today in C or C++ already understands object lifetimes and Rust just adds a static checker for them. In such projects churning out lines of code is not the bottleneck, ease of development should not be prioritized over long term maintainability. Why on earth would you try to rewrite python CRUD apps in Rust?
- moonchrome 3y ago>Anyone writing these things today in C or C++ already understands object lifetimes and Rust just adds a static checker for them. As someone who only used Rust casually - understanding object lifetimes and knowing how to encode this in Rust type system is not the same thing. Not to mention that Rust can't statically prove some things that are valid (eg. cyclic references).
- twic 3y ago> Anyone writing these things today in C or C++ already understands object lifetimes and Rust just adds a static checker for them. I've certainly seen seasoned C++ programmers saying this. Of course, a few of them of say they understand object lifetimes so well, they they don't need the static checker! > Why on earth would you try to rewrite python CRUD apps in Rust? This is one of the great mysteries of our times. I do think the enthusiasm for using Rust for web apps and such (a) is misplaced and (b) has been a drag on Rust developing into a better C++ replacement.
- bluGill 3y ago> Of course, a few of them of say they understand object lifetimes so well, they they don't need the static checker! There is a difference between understanding lifetimes and being able to keep track of them. I have a lot of objects in my more than 10 million lines of code. Most of them have simple lifetimes that are easy to track, but a few for reasons (which may or may not be valid - often the reasons are it was built in C++98 and updating to modern lifetimes is hard when it is used all over) have complex lifetimes that are tedious to track. It isn't that I can't, it is that I get bored/make mistakes and the static analyzer wouldn't (Or course C++ can't be statically analyzed, but if it could the static analyzer wouldn't fail for the same reasons I fail)
- ZephyrBlu 3y agoThis is an interesting read, because I read it as "I would have done all these things which would have kept the language more pure to my vision but less accessible". I also found this bit interesting: "It's easier to work with than C++, but that's fairly faint praise". I see this kind of thing in my own personal projects all the time. I'm thinking "oh it would be really cool if I built X" when in reality most of the time users just want really simple stuff. Being easier to work in than C++ might be faint praise, but it's probably the biggest draw of Rust for me. I don't want to touch C++ with a 10ft pole, but I love using Rust.
- masklinn 3y agoNote that the quote is specifically about parsing Rust syntax, it’s not about the language in general (which is a lot easier and safer to work in than C++).
- ZephyrBlu 3y agoTrue, but I feel like the sentiment generalizes very well. I'm sure that C++ is perceived to have a similarly low bar in many areas.
- truculent 3y agoI'm not sure it would be less accessible. I think the trade-offs would lean towards simplicity, and perhaps less familiarity. But with the right mental models, I think this could enhance accessibility (less "magic", or strange edge-cases). For example, see the discussion on not minding if users have to write something in a more verbose way if it preserves the language's principles. This type of trade-off is something that lowers the barrier to entry for beginners, who don't mind writing things out the long way.
- ZephyrBlu 3y agoI'm using accessible in a very general sense. The sense of "how niche would this be". My impression is that Rust would have been a very niche language if Graydon was the BDFL.
- truculent 3y agoIt sounds like the Rust He Wanted has a lot of thematic similarities to Elm. Interestingly, Elm has a BDFL, and a development process that reflects that. And he’s right - there are a lot of people who really don’t like that! Overall, a really interesting article. Though I like today’s Rust, I do think I would prefer the trade-offs made by the alt-Rust outlined here. Perhaps it’s just my own personal preference, but I think there is a strong bias in users towards what they are already familiar with, and it’s hard to break away from those without a BDFl or similar position of authority who can impose their vision.
- EdwardDiego 3y agoMy understanding is that for the Elm BDFL, the B was dropped.
- truculent 3y agoThe language creator has preferred to work on the development of the language largely in private, for the last couple of years. He’s explained why he’s chosen to do this and why he thinks it is beneficial. But, understandably, some people haven’t take too well to the lack of updates. I think whether you view that as benevolent or not (I would, because I agree with lots of de facto development standards being detrimental to language quality, but I understand that that is my opinion and not hard fact) is in the eye of the beholder.
- EdwardDiego 3y agoI was more thinking of a) the ring-fencing of native code and b) his conduct in discussions about such things. Guido was never that abrasive.
- camgunz 3y agoI would love to play with the language Graydon describes here.
- dathinab 3y agoOne thing I want to add wrt. "Cross-crate inlining and monomorphization. I wanted crates to allow inlining inside but present stable entrypoints to the outside." [..] is that it was in general well desired AFIK by most developers but so far out of scope that you probably would need to had the resources rust has today _before_ the 1.0 release to get it done right. At lest with the state CS research had been at during that time. By now due to various reasons (e.g. swift) there is much more research in that direction already done hence a new language has it much easier.
- estebank 3y agoI think this is something that Rust might try again at some point, as part of a stable rust to rust ABI.
- dathinab 3y agoThe problem is that it's not that simple to make it work nicely you need to design you language around such constraints. Trying to do it the other way around is even harder. For example rust in it's current design relies quite a bit on the combo of: generics monomorphisation + inlining + dead code elimination. But this reliance doesn't play well with an stable ABI. Similar features like generic associated types and similar do not make the story easier. Like an rust stable ABI likely would only support `dyn Trait` and no generics or "on the fly" provide a `dyn` variant for generic method where possible. But even that isn't really good enough for a lot of use cases in a lot of different ways. Additionally a ton of important rust things are not `dyn` compatible at all. Even some of the "easy" to solve things aren't that easy for non-technical reasons. E.g. a lot (but not all) of `impl Into<T>`, `impl AsRef<T>`, `impl Borrow<T>` etc. cases are best handled for a stable ABI context by aplying the single function of the trait (`.into()`,`.as_ref()`, etc.) _before_ calling the function and only having an ABI stable version for that. The side of which traits qualify for this is easy (you annotated the traits) the "when not apply it even if it seems valid" part isn't that easy not for technical reasons but for communication/documentation/avoiding unexpected outcomes reasons.
- qaq 3y agoWill be interesting to see how things play out in Mojo as it looks like they will account for lessons learned by Rust community.
- Aardwolf 3y ago> Tail calls. I actually wanted them! I think they're great. And I got argued into not having them because the project in general got argued into the position of "compete to win with C++ on performance" and so I wound up writing a sad post rejecting them I don't understand the subtleties here: Is tail calls an optimization the compiler can do irrespective of the language? Or is there something that prevents this and requires the compiler to use stack here? Is there any visible effect to the programmer from supporting tail call or not, other than performance and stack depth? How does not supporting them compete with C++ performance?
- layer8 3y agoIt’s about stack size. Programs that rely on tail calls (in particular recursive ones) may cause the stack to overflow when the language implementation doesn’t actually support tail calls, for example when using tail calls to recursively process a list that is larger than (some constant fraction of) the stack. With an infinite stack, it would just be an optimization, but in practice the stack is finite (and significantly smaller than the heap), and thus doesn’t lend itself to such a programming style when the implementation doesn’t support tail call optimization.
- Aardwolf 3y agoWhat I actually meant to ask is: given what you said, is supporting it then even a language feature, and not a compiler optimization instead? If rust says they don't support it, does it mean they don't even allow the compiler to do it? Obviously the syntax of the language itself already supports calling the function itself, and whether tail call optimization is supported or not doesn't affect the visible result afaik (except in case of stack overflows / performance)
- layer8 3y agoIt’s a language feature in the sense that it determines which programs are viable in the language. This is similar to garbage collection. In principle, you never have to explicitly free memory. Given infinite memory, garbage collection would only be an optimization. But since memory is finite, it becomes a language feature. Without garbage collection, programs that don’t free their unused memory will typically run out of memory sooner or later, similarly to how a tail-calling program will run out of stack space if the language doesn’t support it.
- neonsunset 3y agoI can't imagine Rust being even remotely viable without having generics or using LLVM to target a wide variety of platforms with sufficiently good codegen quality.
- pmontra 3y ago> The priorities I had while working on the language are broadly not the revealed priorities of the community that's developed around the language in the years since Isn't that a matter of self selection? A language which developed around those priorities would have a community sharing those priorities now. The point is if that community would be as large as the current one, larger, smaller.
- layer8 3y agoThe fact that the community that formed trended in that way can be taken as an indication that those directions attracted more people than the original vision. Note how often Graydon was basically outvoted on design decisions. It would have been conceivable for the project to attract mostly people that fully shared Graydon’s vision, but that’s apparently not what happened.
- kryptiskt 3y agoIt's not really mentioned in the post, but one thing Rust had since fairly early on was a use case, it was used to build a browser engine. As I remember it from the time, the feedback from Servo development tended to pull Rust in a more performance-oriented direction.
- p0nce 3y ago> First-class & Interestingly like Graydon suggests this and 'tis something D has, you can only have `ref` for function parameters. This is something the users sometimes complain about, but I guess it has positives.
- FeepingCreature 3y agoYeah a lot of these features sound like he wants "D with lifetimes".
- sour-taste 3y agoWhat a wonderfully self aware and honest piece of writing.
- tormeh 3y agoI think Rust is somewhat cumbersome as a language, but I also think the right tradeoffs were made. There are far fewer and far worse competitors in the high-performance space than in the general purpose space.
- Decabytes 3y agoI know we haven’t gotten to that point yet, but I’m curious to see if in my lifetime we get a successor to Rust that fixes a lot of issues people have with the language now.
- mjburgess 3y agoOver the evolution of Rust, I've been increasingly despairing about many of the things Graydon here dislikes. I assumed the present "syntactical insanity" was, somehow, intended; it seems, really, it wasn't. I find Rust basically unusable -- at the level of abstraction I want to write code, basic definitions break line limits. Rust seems to be a repetition of C++'s mistake: a language which conspires you to pretend it's another. There are now nearly as many Rusts as C++s. If I return to any domains where Rust would be relevant, I'd probably now opt for Zig or equivalent.
- laeri 3y agoCan you give an example where Rust is unusable? I have been getting into Rust recently and it feels very natural after getting accustomed to dealing with `Result` and `Option`. And what do you mean about "a langauge which conspires you to pretend it's another"?
- mjburgess 3y agoI've just been browsing, eg., https://github.com/robot-rumble/logic/blob/master/lang-runners/python/src/main.rs https://github.com/robot-rumble/logic/blob/master/lang-runne... via https://github.com/RustPython/RustPython/blob/main/jit/src/lib.rs https://github.com/RustPython/RustPython/blob/main/jit/src/l... Have a look at real-world rust repos that are more than simple application code. Personally, I feel like I'm being visually assaulted.
- laeri 3y agoWhat is it that gives you problems? The first example mainly uses a method chaining style of programming which might throw you off? Or maybe the use of lambdas? The first example seems quite readable to me. Also no heavy usage of generics or heavy type sorcery which would be more confusing. The second example also isn't visually assaulting. The struct definitions have macro annotations but doing this in any kind of language would lead to more verbose code. I think the main problem might be if you are familiar with functional languages which lean heavier on data flow and lambdas.
- jimwhite42 3y agoOn the "Async/await" wrt IO and FFI, I wonder what Graydon and others think about the Erlang BEAM or the GHC runtime implementation.
- smitty1e 3y ago[flagged]
- FrustratedMonky 3y agoGreat read from a creator of a language. There are so many new languages these days, it is always enlightening to hear the author discuss design tradeoff's. That being said, man, its easy to forget how difficult and complicated creating a good language can be. Makes me wonder if things like Linux, or C++, were historical anomalies, the stars aligned. How many good projects fail because of 'loosing arguments' that should have been won, or the community didn't form, etc... a million things..
- weinzierl 3y agoOne thing I wished was on this list, but wasn't, is syntax. I love many syntax decisions Rust made, but I wish Rust hasn't borrowed so much syntax from C/C++. The syntax of these languages was designed under (for todays standards) weird keyboard and encoding constraints and many choices are just odd. To give you a few examples: - = instead of == for equality would have been the natural choice - := for assignment is similar enough to what is used in math for definition, so that languages like Pascal use it - <> for inequality is something SQL got right Smaller things that bug me are the ubiquity of the double colon (::) and the weird mixture of snake case and camel case conventions. And not to leave the wrong impression, I think Rust got many things very right. My personal highlights are: - -> for the return value - concise keywords like `fn` - `where` for constraints In general more Algol/Pascal and Haskell - less BCPL and C/C++.
- jstx1 3y agoSyntax is mentioned in the article - it's under "Complex Grammar".
- epage 3y ago> - := for assignment is similar enough to what is used in math for definition, so that languages like Pascal use it I think its cppfront that is taking the approach of `:=` being a declaration with the type being inferred (ie shorthand for `: Type =`). Reading up on that has made me the most ok with applying this to functions (which I see coming up more these days) but I think i still prefer functions having a more distinct look as I process them differently when reading. Now, cppfront's approach to types I think is bonkers, making critical details hard to find except maybe through convention. https://github.com/hsutter/cppfront https://github.com/hsutter/cppfront > <> for inequality is something SQL got right Maybe I'm not recognizing the biases of my own learning background but this never reads right to me vs "not equal" / `!=`. > - concise keywords like `fn` In other discussions, it sounded like Graydon had an upper limit of 4 characters for keywords https://www.reddit.com/r/rust/comments/13oemrg/question_about_ret_being_replaced_by_return/ https://www.reddit.com/r/rust/comments/13oemrg/question_abou... For me, I had a "whoosh" moment for `fn` and always thought it a weird abbreviation, completely overlooking "fn" keys on laptops.
- xiphias2 3y ago,,I would have traded performance and expressivity away for simplicity'' ,,A lot of people in the Rust community think "zero cost abstraction" is a core promise of the language. I would never have pitched this and still, personally, don't think it's good'' If the language makes compromises in performance, it's not a real C++ competitor anymore. Some things are not about what people ,,like'', but that we need a language that is safe and can compete with C/C++ in performance for systems level programming, as most security problems in the world come from C/C++ memory management. If it's significantly slower than C++, Mozilla couldn't have picked it up to replace C++ code base, as there was a huge competition in performance between browsers.
- bo1024 3y agoYeah, I think most of this is implied in the article.
- bluGill 3y agoRust does make compromises of performance. That is not always bad so long as the compromises are minor. Fortunately Rust can do most of the checking at compile time, but it if you read from an empty vector Rust doesn't have undefined behavior and that means there is a runtime check of some sort in at least some cases. The trick is to find the right place to compromise so the cost is minimal overall even if it isn't zero.
- xiphias2 3y agoDropping to unsafe rust is quite easy as long as you understand what you're doing (and reading pointer is generally unsafe). In the case of automatically upgrading from int to bignum, or green threads, going lower level would be much harder. I just wish Rust stayed focused on being the best systems level programming language (for example finishing the SIMD package, getting into stable Rust, getting language level GPU integration similar to CUDA / OpenCL). PyToch, and now the newer GGML for example is still written in C++ for example I still like the changes being made in the language, just not the focus.
- tialaramex 3y ago
- anonyfox 3y agoI love Rust and built some production code with it in the past. But nowadays I want something more simple so that not-so-senior developers can pick it up quickly, and I want flawless tooling, and willing to sacrifice a bit of performance. So basically I often end up with Go. Go is exceptionally great in tooling, ecosystem, any objective metrics like build times or crosscompilation... but I still don't like the language itself personally. If there would be something just like Go, but with a bit more powerful typesystem like Rust has (Option<T> instead of `err != nil`, and so on), and a simplified ML-like language instead of an imperative one... that would be my dream.
- jeltz 3y agoYeah, that is exactly what I want for when I build web applications. Something with an ecosystem like Rust's, with more advanced type system than go but which sacrifices some performance for ease of development.
- californical 3y agoI feel like Crystal is close, they just need more community to build out their ecosystem. Otherwise it seems like a perfect language (fun, simple to understand, compiled + fast, has types)
- anonyfox 3y agoAlready played with it, what has killed me are the outragously long compile times for nontrivial code and no "easy" way to crosscompile binaries, besides from some docker hack. Also its like a modern Ruby, which is great in general, but I really want ML-like functional style programming instead of OOP
- jjtheblunt 3y agoHave you dismissed F# ?
- hajile 3y ago
- javajosh 3y agoToo bad graydon didn't get his way with build times. I've come to believe that the most important feature of any development environment is to minimize the built-test-debug cycle. Of course, a real system has many different ones, ranging from "language level" to "I have to redeploy and perform a complex series of actions in an app or 3". But at the language level I've found that build performance is of paramount importance. And when a project ignores build perf, everyone suffers every time they build. Since the lower-limit is the language compiler, it should therefore be kept very fast. (And the people working on the applications must constantly resist adding features that slow the BTD loop down any further.) A good example of this trade-off in Java is Lombok. A very handy library that legitimately avoids a ton of boilerplate, but it also absolutely tanks your build time. In a real system, a large one, your team is better off just getting good enough with their editor that they can generate the hateful boilerplate, and leave Lombok out. Because you'll be paying for Lombok all the time, and only need it a small fraction of the time. There are hundreds, thousands of these conveniences that are deeply tempting but should be avoided, in every build. The problem is that the programmers become attached to these little nicities and actively resist giving them up, even though they are so costly.
- zamalek 3y agoI don't understand the big issue with build times: I have always found that they are almost instant for incremental builds (assuming you use lld or mold).
- bluGill 3y agoIn C++ a small change to a header can result in having to rebuild thousands of different files. Even if each file builds fast the total can be long. I have also benchmarked including a specific header (not using it, just including it) costs .5 seconds which adds up quick in those thousand files. Another benchmark found a specific boilerplate code construct added .1 seconds to the time to compile the file each time you added that one line - and it was a line commonly repeating in a header (MOCK_METHOD from gmock - there is a FAQ entry on how to get this time down)
- krupan 3y agoThe key challenge of rust for me: "Complex grammar. I've become somewhat infamous about wanting to keep the language LL(1) but the fact is that today one can't parse Rust very easily, much less pretty-print (thus auto-format) it, and this is an actual (and fairly frequent) source of problems. It's easier to work with than C++, but that's fairly faint praise. I lost almost every argument about this, from the angle brackets for type parameters to the pattern-binding ambiguity to the semicolon and brace rules to ... ugh I don't even want to get into it. The grammar is not what I wanted. Sorry."
- kzrdude 3y agoIs there a practical issue with this, or is this more philosophical?
- cryptonector 3y agoIs there anything easier to parse than Lisp? Plus you get homoiconicity and `quote` is free. But... it's ugly.
- krupan 3y agoI'm not parsing expert, but being hard to parse makes it harder to write tools that work with the language. Personally I find rust to be not easy at all for humans to read, and so it's interesting that it's also hard for parsers to parse. Not sure what was optimized for in the design.
- kzrdude 3y agoI've coded a moderate amount in Rust since it was born, I think the prevailing rustfmt style is too bent towards machine-perfect neatness (one example: function definitions are split so that every parameter has a new line). This machine perfect neatness comes from lots of small places in the syntax where Rust decided let's make the syntax permissive so that it's easy to autogenerate code with some macro or to make good diffs. Then a systematic implementation of trailing commas and allowing leading/trailing separators in some places. The result is quite sterile and to me is no longer organically nicely readable. tldr: rustfmt has no soul
- bazoom42 3y agoTo be successful, it is not enough for a language to be good. It might not even be necessary. What matters is if there is s significant niche where the language is a better fit than any alternative. PHP show that a language only needs to get that one thing right. Rust have found its niche. Graydons vision seem to be a more elegant language which would compromize on the points which actully make Rust succesful.
- kaba0 3y agoWell put. Rust wouldn’t be anywhere near this big/hyped if it would have been a new ML.
- sapiogram 3y ago> What matters is if there is s significant niche where the language is a better fit than any alternative. This is a wonderful comment, and puts into words something I've been thinking for a long time. The best general-purpose languages always seem to start out with a strong niche, then grow from there.
- demarq 3y agobeautiful ending!
- rurban 3y agoInteresting. So it looks like once he let the C++ folks in, they started to damage it. As they did with their own design decisions before.
- sapiogram 3y ago> So it looks like once he let the C++ folks in, they started to damage it. At least in terms of his personal preferences. I don't think it's true in terms of market share, given the massive success of Rust.
- titzer 3y ago> Library-defined containers, iteration and smart pointers. Containers, iteration and indirect-access operations (along with arithmetic) comprise the inner loops of most programs and so optimizing their performance is fairly paramount; if you make them all do slow dispatch through user code the language will never go fast. If user code is involved at all, then, it has to be inlined aggressively. The other option, which I wanted, was for these to be compiler builtins open-coded at the sites of use, rather than library-provided. No "user code" at all (not even stdlib). This is how they were originally in Rust: vec and str operations were all emitted by special-case code in the compiler. There's a huge argument here over costs to language complexity and expressivity and it's too much to relitigate here, but .. I lost this one and I still mostly disagree with the outcome. Trust me, you do not want to put this stuff into the compiler. It's not just that it's cheating for perf, but it's confusing to users (no source code to read how these work) and frustrating that they can't write their own. Ultimately what this really means is that these things are indeed written in some language--the compiler's IR. JavaScript actually has a ton of this kind of things and every JS engine has gone through multiple generations of "what language do we write Array.sort in!?". In V8, these intrinsics are written in a DSL because doing them in asm, a special dialect of C++, or one of two compiler IRs ended up being more trouble than its worth. You want a clear separation between what is language and what is library.
- marcosdumay 3y agoAlmost all high-level languages have builtin containers. I do think it's a bad fit for Rust (at least for what Rust became), but it's not the end of the world by itself. The fact that JS has about 3 of them (is it only 3? I'm not sure of this), with different interfaces, and non-usual behavior is what creates problem there. But other languages quite successfully make their own containers either different enough or similar enough that it's not a problem.
- paulddraper 3y agoArray Map Set WeakMap
- 3y ago
- avgcorrection 3y agoI haven’t cared about what Hoare thinks of Rust since 2015. 1. He hasn’t been involved in the language for a long time 2. His vision for the language was completely different compared to how the remaining developers ended up designing it. So if I ended up liking Rust under his “BDFL”ing then it would be for completely different reasons compared to why I like (and dislike) Rust today
- avgcorrection 3y agoHmm, I had only read a few paragraphs when I wrote that. Now I’ve read through the whole thing and it seems that Hoare agrees with me. How nice.
- sheepscreek 3y agoI’ll get straight to the point I want to make: Rust is suffering from an identity crisis. Much like Javascript. Realizing this, I thoroughly feel the need for a “Rust, the good parts” doctrine. A good portion of use-cases could be successfully implemented with a small subset of language. The small subset doesn’t need to be any more complicated than Go. And in doing so, we’d be reducing the entry barrier for masses and encouraging wider adoption. Edited: For clarity
- davidatbu 3y agoCan you expound upon why Rust is having an identity crisis? Rust's current mission is: "empowering everyone to build reliable and efficient software." It seems like it's hitting that goal to me (for .e.g., it empowered me, a person who's never written serious code in C/C++, to write wasm-based speech recognition reliably and efficiently). Also, what is the identity crisis that JS is having?
- MontagFTB 3y ago> Not 100% clear about actors -- I was weirdly focused on that model that in practice has many issues… Any ideas what he meant here?
- bfrog 3y agoAfter reading this I'm really quite happy Graydon created Rust, but then conceded the path it has taken. It really is an incredibly language and ecosystem, in large part, because of its performance potential. To be clear, the only real options in this space were arguably C, C++, and maybe in some circles D in my mind. C++ and C by far had the mind share. Had Rust gone the way Graydon wanted I don't think Rust would be so interesting in the OS and Embedded space. This is a space that it turns out is really ripe for change. Embedded application are growing more connected, and more complex all the time. Security is a serious concern perhaps followed by or proceeded by performance depending on who you ask. Rust checks so many boxes off in this space its really hard to argue that it isn't a better solution. Would you rather write a little embedded http server on an IoT device in C, C++, or Rust? What about an embedded networking stack? What about a mesh network stack? I know the answer I'd have every time for this myself.
- fallat 3y agoZig
- 0xDEF 3y agoRust moved in a direction where it is now a suitable alternative to C/C++ all the way down to operating system code and bare-metal embedded firmware. Graydon wanted something else even before Rust 1.0 was released. He wanted an OCaml-like language with modern Go/Erlang-inspired higher level concurrency abstractions.
- hardwaregeek 3y agoA lot of Graydon's ideas feel like interesting extensions to ML-style languages. I bet if he had continued down that path, it would have been a lot more of an experimental language with a hodgepodge of different ideas. Which is totally valid (you need these languages to test new paradigms and features), but definitely would not have become mainstream. Basically, I view Grayson as a leader who set the tone for Rust being a language that was willing to take ambitious swings on cutting edge features. But I don't think he would have been the person to eventually make the cuts and compromises necessary to hew the language into a cohesive, mainstream language. Rust ending up as a replacement C++ helped it not only determine which features to keep and which rules to follow, but also helped it create the right pitch for developers to use it. This does lead to a larger question about BDFLs. Perhaps, like CEOs, the BDFL you want when you're starting a language is not the BDFL you want when you're maturing a language, or maintaining a language. Especially around feature selection, in the beginning it may pay off to add a lot of features based on user feedback, but later on it may be better to push back more. And from a psychological standpoint, I have wondered about the pressure of being a BDFL. Grayson has been open about stepping down partially due to reaching his limits, and I suspect other BDFLs have thought about it too. The job sounds exhausting and thankless. At a certain point, wouldn't you want to leave and start a new project? And wouldn't we want the person who had success once to give it another shot?
- dataflow 3y ago> Rust ending up as a replacement C++ helped it If anything, it's more a C replacement than a C++ replacement. It will take some market share from both of course (and other languages to a lesser extent too), but functionality-wise, it just isn't (currently, at least) practically able to replace some C++ use cases.
- badrequest 3y agoI'm interested in more on this. What can I do in C++ that I can't do in Rust?
- steveklabnik 3y ago
- pjmlp 3y agoWhile it has a been a great piece of wrong to introduce affine type systems into mainstream, it hardly justifies outside domains where any kind of automatic memory allocation isn't either a blocker, or religious issue that won't be sorted out even by proving the contrary. I see the ongoing attempts to add linear types for low level coding, alongside automatic resource management more future proof.
- svieira 3y ago> Not 100% clear about actors -- I was weirdly focused on that model that in practice has many issues Does anyone have any insights on the particular issues with actor-based concurrency vs. "direct parallelism like threads or locks" that he might be thinking about here?
- olalonde 3y ago> Explicit lifetimes I never understood that one either. There is always only one "solution" that will make your program compile, so why not just let the compiler figure it out?
- steveklabnik 3y agoI wrote a blog post about this. https://steveklabnik.com/writing/rusts-golden-rule https://steveklabnik.com/writing/rusts-golden-rule I did not mention lifetimes, but the principle is the exact same: the lifetime annotations are an API promise, and so inferring them means that a change in the body of the function would change the promise, breaking other code.
- junon 3y ago> I was weirdly focused on [the Actor] model that in practice has many issues I maintain the actor model is probably the most theoretically perfect concurrency and distributed computing model. The holy grail. We just don't have the right hardware for it and it's extremely limited by addressability issues with current technology. So I don't really find this surprising, nor disagreeable. It's just not a model that Works Well at present.
- derefr 3y agoI'm not sure I agree. Runtimes like Erlang's work great for many things. You just have to be aware that actors aren't going to magically get you more CPU cores — i.e. you can have as many IO-bound actors as you want; but a CPU-bound actor (done correctly, such that "gets out of the way" of actor scheduling) is just a regular CPU-bound preemptive OS thread; and you can only realistically have as many of those as you have CPU cores in your machine, before you start experiencing highly degraded performance. Most systems don't need more than 100 (different) CPU-saturating things to happen at a time. If you do, actors won't save you... but nothing else will, either. You'll need to scale horizontally. (At which point, the actor model becomes very useful from another perspective — that of transparent distribution of messages between nodes.) But tbh, there's a reason that, even on the systems Erlang was originally designed for and is "idiomatic" for — those being telecom packet switches — the Erlang software only performed the role of the control plane. There was also a data plane in each of those boxes — some kind of FPGA or ASIC — designed specifically for the job of applying a list of active routing rules at each input port, such that packets on that port would be unwrapped, maybe filtered, route-matched to an output port, maybe buffered to combine with other packets, then re-wrapped and emitted at said output port. The job of the Erlang code was to listen for signals bubbled up from the data plane, in order to build complex state-machines, do accounting, etc., resulting in change commands being pushed back down into the data plane ruleset. Actors are great for keeping a bit of local state in order to make decisions, and coordinating with other actors and their local state to make more complex decisions. Actors implemented naively — where all actors are uniformly green threads — are not so great for doing the same thing over and over, at scale. Telling N actors to do the same thing is no substitute for a DSP, nor for a tensor core. But this isn't an indictment of the actor model, nor of current hardware, but rather of the current state-of-the-art in actor-model languages. You could totally create an actor-model programming language where actor-pools that are doing SIMD are transparently "promoted" during compilation into GPU shaders / FPGA gate-networks / etc. Nobody's done it, but there's nothing stopping anyone. (Anyone interested in trying this could probably do a proof-of-concept on top of Elixir's Nx library.)
- parasense 3y agoHe's already created several programming languages, and there is still time to create his ideal.
- Lk7Of3vfJS2n 3y agoHas Rust gone beyond the point of no return? Have less elegant features possibly been embedded in the language that have put Rust on the track to never become the hypothetically perfect or unblemished language?
- steveklabnik 3y agoThe answer to your second question is "yes" for every single language that's ever been made or will be made.
- Lk7Of3vfJS2n 3y agoAre you saying a hypothetically perfect language is unattainable? Why? Is there proof for this?
- w10-1 3y agoGraydon may lament the features that got away, but being a good loser may be the best way to encourage contributions and to respond to community needs. The historical forces on a language are both its constraints and its drivers. Languages that are nice conceptually are not responsive to history. Both Swift and Rust both veered away from their original champions. The champions helped by focusing the problem and providing a technical skeleton, but the need (the pain of C/C++/Objective-C) was both intense and complex, so the community was stronger than the BDFL model. Interestingly, Swift has seen Rust forge ahead on a number of fronts, but is quietly adopting the best of Rust, and soon interoperating with C/C++ will be frictionless. The ties to Apple are being loosened, with a more portable stdlib and a Foundation library that subsets the legacy Apple Foundation instead of dragging Apple API's into other platforms. If/since Apple is to rewrite its systems in Swift, Swift will likely evolve into the best language for migrating off C/C++. Compare Graydon, von Rossum, or Chris Lattner to Java's Mark Reinhold. Mark has been quietly at the helm of Java since 1997, navigating: the Oracle and open-source transitions, partners ranging from IBM to broad developer communities, continuous VM updates that kept Java relevant, and the quick pace of recent language/library upgrades: lambdas (method and field handles), vector processing and FFI, native...
- codedokode 3y agoI don't understand why in Rust integers wrap around. It doesn't make sense and there are vulnerabilities caused by wrapping integers in C.
- sdfghswe 3y agoWhat's the alternative? What would you expect happens?
- codedokode 3y agoPanic so that the invalid value doesn't get stored into the database or somewhere else. The developer then would notice the problem and fix it. Silently using invalid value is the worst choice.
- sdfghswe 3y agoPardon my ignorance, but what does "panic" mean, specifically?
- garbagecoder 3y ago>a viable c++ alternative Wow, so one of the principal creators understands that that's what it is, not a replacement for everything under the sun. And it's a GREAT c++ alternative, but ffs please stop telling me to use it for everything from webdev to embedded.
- aidenn0 3y agoI wanted nearly the same language Gradyon wanted, but I also suspect that my tastes are insufficiently mainstream for a language to my tastes to be as popular as Rust has become (much less as C++ is).
- cryptonector 3y ago> Environment capture. I often say (provocatively) that "I hate lambda", but lambda is actually (at least) two separate language features: one is a notation for anonymous function literals; another is equipping those anonymous function literals with environment capture. I don't really care either way about having such a literal syntax, but I really do dislike equipping it with environment capture and think it's a mistake, especially in a systems language with observable mutation. Early Rust had something called "bind expressions" which I copied from Sather and which I think are better (clunkier but better). Rust gained lambda-with-environment-capture in a single package which I didn't object to strongly enough, as part of trying to make interior iteration work on LLVM-with-no-coroutines, and this motivation was later removed when we moved to exterior iteration. But "if I were BDFL" I would probably roll back the environment capture part (it's easier to tolerate for non-escaping closures which many are, eg. in non-escaping coroutines / stack iterator bodies, but .. eh .. complex topic). TFA loses me here. I rather like the Fn/FnMut/FnOnce business, though yeah, closures of dynamic extent are very limited unless you Box them to make them of indefinite extent... and so the whole language lacks that character that functional languages with GCs have, but it's still functional, just functional with a straight-jacket. Earlier in TFA there's a mention of exterior iteration as in generators, and I want to point out that while generators are very nice, they are not a substitute for closures. Icon, for example, had iterators and first-class co-routines ("co-expressions"), but no closures, and so where one needed closures one had to use co-routines (costly!). It's true that with generators one needs closures less than without generators, but still, closures are very important. > 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. 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". This loses me too. It's great then that Rust didn't have a BDFL! :) > Underpowered existentials. The dyn Trait mechanism in Rust allows runtime and heterogeneous polymorphism, a.k.a. Existentials. These types are useful for many reasons: both solving heterogeneous representation cases and also selectively backing-off from monomorphization or inlining (when you have those) in order to favour code size / compile time or allow dynamic linking or runtime extension. Early Rust tried to use these extensively (see also "first-class modules") and actually had an intermediate-rigidity type called an obj that was always a sort of Cecil-like runtime-extensible existential glued to a self-type record that allowed method-by-method overriding at runtime (almost like a prototype-OO system). Today's Rust strongly discourages the use of any such dynamic dispatch, a feedback loop arising from both technical limitations placed on them and a library ecosystem that's taken that as a sign never to use them. This, on the other hand, is a brilliant observation and I agree with it as with much else in TFA. > Tail calls. I actually wanted them! I think they're great. And I got argued into not having them because the project in general got argued into the position of "compete to win with C++ on performance" and so I wound up writing a sad post rejecting them which is one of the saddest things ever written on the subject. It remains true with Rust's priorities today, I doubt it'll ever be possible across crates (maybe maybe within), but as with stack iterators IMO they're a great primitive to have in a language, in this case for writing simple and composable state machines, and "if I were BDFL" I probably would have pointed the language in a direction that kept them. Early Rust had them, LLVM mostly made us drop them, and C++ performance obsession kept them consigned to WONTFIX bug status. Oh dear. TCO is essential, IMO. I understand that it may not be possible in cross-crate cases, but still, TCO is very important.
- mcguire 3y ago"Exterior iteration. Iteration used to be by stack / non-escaping coroutines, which we also called "interior" iteration, as opposed to "exterior" iteration by pointer-like things that live in variables you advance. Such coroutines are now finally supported by LLVM (they weren't at the time) and are actually a fairly old and reliable mechanism for a linking-friendly, not-having-to-inline-tons-of-library-code abstraction for iteration. They're in, like, BLISS and Modula-2 and such. Really normal thing to have, early Rust had them, and they got ripped out for a bunch of reasons that, again, mostly just form "an argument I lost" rather than anything I disagree with today. I wish Rust still had them. Maybe someday it will!" I remember that one. The change was shortly after I started fooling with Rust and was major. Major as in it broke all the code that I'd written to that point. "Async/await. I wanted a standard green-thread runtime with growable stacks -- essentially just "coroutines that escape, when you need them too"." I remember that one, too; it was one of the things that drew me to the language---I was imagining something more like Pony (https://www.ponylang.io/ https://www.ponylang.io/). "The Rust I Wanted probably had no future, or at least not one anywhere near as good as The Rust We Got." Almost certainly true. But The Rust We Got is A Better C++, which was never appealing to me because I never liked C++ anyway.
- superkuh 3y agoFunny how every time I click a link to a dreamwidth.org hosted blog the, >"Hello, you've been (semi-randomly) selected to take a CAPTCHA to validate your requests. Please complete it below and hit the button!" ...pops up and the button doesn't actually work. Truly one of the worst blog hosts out there if you actually want everyone to be able to read what you write.
- worik 3y ago> basically every language discovers the long way that financial math is special and, at great length, eventually adds a decimal type. And every case it is wrong Financial math is not hard when you know how Use integer types not horrific cludges like "decimal" Just because IBM did it does not make it right. It is wrong
- cmrdporcupine 3y agoWhen I first read Graydon talking about his plans for Rust, I pictured it as StandardML (or OCaml) without a garbage collector, and I was sold. This list doesn't look fully like that, but is closer than current Rust is. My interest back then was in a higher level language with type inference and a modern ML-like type system but that could be used for systems programming, especially in database, virtual machine, and even operating system dev. These days I work pretty much full-time in Rust, and I think Rust as it is today delivers on some of that promise, but not all. I feel like the language's borrowing and ownership checking are pretty brilliant but really begin to become a pain when dealing with nested and interrelated trees of objects and iterators (like if building a compiler or query evaluator, etc.), and resorting to Arc/Rc/RefCell, etc. feels awkward. I'm not sure if the language Graydon talks about here would have been better for that or not. But I'm also happy we have Rust, because it's an improvement over what else is out there, and I hope the community gets through its growing pains.
- vintagedave 3y ago> The other option, which I wanted, was for these to be compiler builtins open-coded at the sites of use, rather than library-provided. No "user code" at all (not even stdlib). This is how they were originally in Rust: vec and str operations were all emitted by special-case code in the compiler. One of the things I like about Delphi is that it has some powerful types as compiler intrinsics. Sets, strings (the compiler-generated code does call into RTL methods for things like finding substrings, but the string type itself), and so forth are all compiler-generated. I would like to see more, in fact: I think a map type would be a great inbuilt addition. (What I'd really like is compiler stubs so you could link in your own implementation. Whatever is linked in, it's then heavily optimised by the linker to be inlined etc as appropriate.)
- smasher164 3y agoI admire Graydon's humility on the subject--and sure enough, I disagree with some of his ideas in this post, and agree with other ones. - Explicit lifetimes are what make rust what it is. It would have surely failed had they not been introduced. - I disagree about having a first-class module system instead of traits. Coherence and implicit instance resolution are a core value of Rust. `Send / Sync` are key examples of that. - Green threads probably wouldn't been viable for rust, given the kind of programs it's targeting. - Pretty much everything else however, I agree with.