He is complaining about fast 6 week release cycles for rustc, but actually things are petty stable atm. Most releases are just "x is also const now" or "we figured out how to relax type checks to allow this safe program to compile that was previously failing to past muster with the borrow checker".
There hasn't been a big feature since async/await, and the noise around that is now in library user space - as was to be expected.
There is a rust 2021 edition coming up, but that is also looking to be very modest with very few breaking changes. Like adding `TryFrom` to the standard prelude, and deprecating missing `dyn` keyword for trait objects.
I would agree this post is putting the wagon before the horse — the release cadence doesn't really mean anything, the real question is what frequency do new things break your code at.
This "moving target" complaint comes up again and again.
It's the classic elevator issue in reverse. If you want to make an elevator faster, put up mirrors so people look at themselves instead of their watch.
Rust appears to change fast, because the changelogs are so detailed, but actually it's stable. Maybe we need to hide the detailed changelog and replace the main one with "minor bugfixes and constness updates".
Please, never listen to people who complain about big changelogs!
The transparency is hugely appreciated by many. It's just that the approving voices are usually silent while the disapproving ones are always loud. Don't let that mislead you. You are doing great.
>"we figured out how to relax type checks to allow this safe program to compile that was previously failing to past muster with the borrow checker"
While perhaps not a large change in practice, this seems like the sort of thing that incurs a large cost when it comes to updating your mental model of how the compiler works, what it can and cannot do, and what options you have when it comes to implementing something.
The reaction to seeing code using these changes is "oh neat that works now". Every time I see changes like this in the change log, it actually simplifies my mental model, because the rules are the same but there are fewer exceptions.
The end result is a simpler model. The process of simplifying your model may not be cheap.
It's like how you can get some weird set of complex rules and after a bit of time and practice you can just apply them without thinking much about it. However if you suddenly change those rules - even to make them simpler - you'll have to spend awhile readjusting.
It doesn't make the changes bad, but it might explain why people trying to keep up with Rust feel it's changing more significantly than it actually is.
My experience learning and using Rust over the last 9 months has included a lot of repeats of this:
1. Write some code that does something tricky with borrowed types
2. It won't compile. Search online for the error message. Find the Rust github issue about adding support for doing things that way.
3. Try to find or think up a different way to write the code. Go to 1.
GP is referring to changes that make compilation succeed at step 1. These changes will save newbs from many hours of frustration. The cost of these changes is minimal. Actually they free up a lot of mental capacity currently used for workarounds.
I'm really happy with Rust and the steady progress made by the core team. Rust stable is really excellent to work with.
I understand that. And I still think these changes might be particularly expensive ones.
Trying to keep track of what workarounds you do and do not need to use is hard. Removing workarounds is good, but still an expensive step. Applying a large set of rules can be quite easy after an adaptation period, but changing those rules remains hard. Even if the new rules are simpler.
I'm not saying Rust shouldn't be making these changes. I'm just saying I think this might be part of the reason why you hear comments about how hard it is to keep up with Rust.
> this seems like the sort of thing that incurs a large cost when it comes to updating your mental model of how the compiler works
Why?
If you simply do NOT update your model won't that work just fine? You would continue to avoid certain constructs that used to bother the borrow checker; your code would work fine, and the compiler wouldn't complain exactly as it used to.
I agree you don't strictly need to update your mental model, but that doesn't make the update itself less expensive.
I'd guess most people using Rust and checking the changelogs are people who are interested in keeping up with Rust. They are likely to update their mental model because they wish to.
And as a result, they often have to deal with these 'expensive' updates which makes it feel like it is difficult to keep up with Rust.
I can understand it though; if you're on the ball (and you should be, because people have been burned by trying to update things after years of changes), every six weeks you'll get this ping, you need assess what changed and whether you need to take action.
Contrast this to e.g. Go, which has a ~6 month update cycle, and most of the updates are boring. The main thing relevant to me personally for Go's recent 1.16 update is embedding files, and that's more of a "I can use it when I get to it" thing. Rarely does a Go update require action on my part, and since I started using it full time January last year, I've NEVER had to change any existing code. Neither required, nor because the language has solved something more clever.
Granted, that could be considered a bad thing, and I wouldn't mind some additional features to reduce the amount of code I have to write and maintain, but still.
Tbh, for stable rust you don't need to do anything. Breaking changes to the stdlib or the compiler are incredibly rare (because the rust team tests against public crates to see if there is breakage).
You will get broken code if you rely on nightly features or if you change edition. My nightly code breaks about once every few weeks but everytime one or two features begin moving into stable and it gets closer to being on pure stable rust, not requiring any unstable things anymore.
So really, if you're writing rust to against stable rustc, you don't need to pay attention to much.
> [...]every six weeks you'll get this ping, you need assess what changed and whether you need to take action.
Rust's stability guarantees mean that you don't need to take any action at all.
Breaking changes (unless soundness is involved) only happen with editions and even when a new edition comes out and you update the compiler, you still don't need to do anything unless you explicitly change the configuration of the project to the new edition.
The only thing you might want to do, if you use clippy (a linter that comes with the rust toolchain). Is to check whether it complains about your code due to new check. If that's the case, you get told what to change and why.
The key is that even with places with some wiggle room, like type inference, we take care to try and break as little as possible, sometimes not accepting changes we technically are allowed to, sometimes by adding warnings and waiting a long time... that said, you're right that breakage does sometimes happen here, though we work hard to minimize it, and we don't get tons of complaints that this stuff breaks people's code often.
In the places I worked with Rust it's usually excellently understood that upgrading the compiler must be accompanied by a `clippy` session and a careful review of any and all compiler warnings so IMO compiler upgrade is a non-issue even if there are the very occasional breakages (which I never encountered).
1. Rust has very strong stability guarantees. If you want to you can continue coding like it's Rust 1.0 even on the latest compiler.
2. The rate of releases is independent of the rate features are added. Nightly is a playground for feature additions and whatever else. Many may not ever make it into stable, and many might hang around for many years before they are read to be stabilized. A consistent release schedule of every six weeks, whether there's much new or not, means there's no harm in delaying something for a release or three. This vastly reduces the pressure compared to a 3 year release cycle where missing the window means a very long wait.
Rust's releases tend to be very small. Even the big async addition was only the async MVP, not the final product. I think this is probably the source of most complaints because it does introduce some genuine churn for async projects.
But as always this is hard to discuss in the abstract. At least not without some idea of what features people think shouldn't have been stabilized or which they think were rushed.
Btw, here's a good article that attempted to look in to this more objectively:
Rate of features added being high could be directly proportional to our code going obsolete sooner than later. Wouldn't it?
I also understand that Rust is quite backwards compatible which is good but a planned better version of releases would be easier for everyone to keep track, update codes, etc.
Is the rate of features being added high? Things that wouldn't even be a footnote in a new C++ release announcement can be highlighted in a Rust release announcement which may give the impression of lots being added but it ultimately doesn't amount to much.
As long as the compiler remains backwards compatible nobody forces anyone to rewrite programs that deliver their requirements at the time they were developed.
Major compatibility breaks occur on a very long time-frame and most certainly with a version bump prominent enough to draw anyone's attention. Personally, I expect builds to suddenly break on dependencies rather than anything else.
> 1. Rust has very strong stability guarantees. If you want to you can continue coding like it's Rust 1.0 even on the latest compiler.
There have been at least two cases where Firefox build broke due to having a too recent version of Rust installed. The stability guarantees may be fairly strong but it's definitely not perfect.
Use of uninitialized memory is Undefined Behavior. So in a sense, that code never worked properly, but authors didn't know about it until Rust caught it explicitly.
It's undefined behavior. Anything can happen, by definition.
I understand what you're saying, but anyone who knowingly relies on undefined behavior deserves whatever pain they get, and anyone who didn't know they were relying on undefined behavior, needed to know about it.
> the 6-week development cycles. It’s one of the causes of an unhealthy problem: features bloat. It’s also the cause, in my opinion, of another problem: the immaturity of the ecosystem.
Not sure I have the same experience or agree with that. Sure, Rust has a 6 week release cycle, but most of the time the releases are bug fixes or moving library additions into stable.
Take this release for example: the only change is ARM support on Linux and a small update to the test framework. I’d hardly describe that as bloat.
> As a rust developer, I need to remain up to date with the latest developments in order not to produce code that is obsolete as soon as it’s released
Clippy should help with that, it usually flags deprecated code or better/more up to date ways of doing something. I don’t think you need to keep on top of every RFC, just use what you need.
Not he horrible syntax that would make (former)Perl developers shed the tears of joy with how many symbols are used? Not to mention the weirdly shortened words, if I had to write in Rust, I'm sure I'd soon 'mut'(ilate) myself. If you want to save on typing, go the full way and embrace Perl (or APL ;), don't stop in the middle.
Totally subjective, but for me Rusts symbols seem like a good trade-off, where the readability cost paid is worth the gained expressiveness. In comparison, Perl has a terse syntax that harms readability more than it helps in other ways. Again, that's subjective.
Apart from that, Perl is not a substitute for Rust or vice versa, regardless of the amount of typing involved.
The symbols that come to mind when I think about my experiences writing Rust are:
- <> for generics
- ? for early-return errors
- Macro invocations require a !
- Match statements use =>
- ' for lifetimes
- #[attrname] for attributes
- |x,y| for closures
- -> for return types
All the other common symbols I use feel too conventional to seem worth mentioning, like {} for lexical scopes, = for assignment, +-/ for math, foo() for function calls, foo.bar() for method calls, (a,b,c) for tuples, [1,2,3,4] for arrays, <>!== for comparison, "quoted" 'strings', / comments */ and //comments, etc.
I agree that might_fail()? and 'lifetime are different, but everything else I listed seems lightweight, and very common for languages to use symbols for. <> is common for generics from C++, but alternatives I've seen are [] and (), also symbols. Matches use =>, and C's switch cases use :, also a symbol.
Using macro_rules to define macros is pretty symbol-heavy, I guess?
Usually when I see complaints like this, they come down to complaints about the lifetime syntax, and not liking the use of ' for anything besides quoted strings.
If you disagree, could you explain how I've missed or misunderstood your point? Can you show some examples of normal Rust code that uses way more symbols than normal Perl?
I don't think the release cadenece (6 weeks) is the cause for how fast the language was changing.
As a counter examples, Go release roughly every ~26 weeks and mostly has releases with minor updates. Chromium releases every 6 weeks but not every release has major updates; they are mostly bug fixes and minor improvements. Even Android is decoupling its system services into components which can be updated through the Play store at a much faster cadence than their yearly releases.
I agree that Rust needs to now focus on polish over new features at this point, but I'm not sure that Rust should've done something differently, especially around its release cadence. I don't think it would've been a good contender for serious companies if they hadn't invested heavily in async, for example.
Rust has a release every 6 weeks, but there haven't been any new major new features in stable since async await, which was in November 2019. The situation is not too different from Chromium.
It's quite funny that this is a bunch of complaints that they can't keep up with rust development and that they should do things differently but ends with a plug for their book about their experience programming in rust.
I was under the impression that rust is pretty stable?
Like web browsers get updates on a fast cadence and it rarely breaks existing web pages.
Rust is pretty stable. The point is that the work on Rust is happening so fast it's getting impossible to keep track of releases whilst making sure that your code doesn't go obsolete.
I think people just have to learn that "not using the newest features of the language" is not a problem. I have no problem with obsolete code, where "obsolete" means just that. I have a problem with broken code. If it ain't broken, no need to fix it.
One thing that makes these sorts of conversations tricky is that different people mean different things when they say stuff like "going obsolete." To some people, it means "this code literally doesn't work anymore," and to other people, it means "oh no the error handling library I use isn't in vogue anymore and I feel the need to re-write everything to use the latest library."
There is not a lot of the former, but there is some of the latter, and even if it's self-imposed, some people do feel that pressure.
Having critiques of something, or lamenting the subject's complexity, surerly doesn't undermine your position as an expert on something? To think the converse would, I think, steer you toward bad experts.
Click bait article with minimal substance that pitches a book sale? Feels like spam? I guess the topic gives everyone yet another chance to air their hypothetical greviences with rust
Rust has a very strict backwards compatibility policy, and as a result has had ~0 breaking changes since 1.0, with the notable exception of opt-in Rust 2018 edition. Best practises might get out of date, but generally speaking nothing breaks between releases.
This is what I love about Hacker News. There is an article, and there are reasoned objections to it in the comments, which means I can make a bit more of an informed opinion myself. Thanks all!
As others have written, there's basically no connection between Rust's six week release cycle & the rate of actual change to Rust. If Rust switched to a 12 week release cycle, all that would change is that it would take twice as long for features to reach users on stable once they were decided to be released. Feature development is neither release driven nor release constrained.
However, the ground truth is that the design of significant new language features basically stopped in 2018. The work now is shepherding through the language extensions the project already committed to in the first few years after 1.0. For example, const generics, which will have a stable MVP in the next release, was first begun in 2017. Generic associated types, which are still not near stable, in 2016.
And my own view, these remaining features are a nearly "feature complete" Rust. Future extensions will be either more niche (a lot of attention in the last few years has been aimed at features to make writing unsafe code less error prone, which wouldn't visibly impact users who write only safe code) or less substantial (such as a syntactic sugar that would improve a lot of users lives, but not deeply change how they write code). And that's actually very good.
Imagine if Rust only did releases every 18 or 36 months like other popular languages, or every six months like OP wants. Features that haven't been fully baked would be pushed in to the current release because people wouldn't want to wait another 6 months to see their work come to fruition. When the next release is only six weeks away, the cost of saying "aight, let's take our time and make sure it's ready before sending it out" is so small. The MVP of Const generics has been delayed by 6 weeks, upsetting exactly 0 people.
Regular releases of the compiler are awesome for the same reason continuous deployment of web apps is - each release only packs a small number of features. The chances of something breaking are much smaller than if it was a massive release of hundreds of features, all of which need to be tested in isolation and then with each other. The releases page (https://github.com/rust-lang/rust/blob/master/RELEASES.md) shows how rare it is for a fix release to be made. Even when it is, it's something minor.
Making the language easier to learn is a high priority. Many people are working on this actively right now - better documentation, better error messages, better IDE experience and so on. OP has misdiagnosed the root cause and blamed something that actually makes it easier to learn the language.
> Features that haven't been fully baked would be pushed in to the current release because people wouldn't want to wait another 6 months to see their work come to fruition.
This psychological tinkering isn't helpful. People can push unfinished stuff in any situation. E.g. you can close it off 5 months in and then stabilise for a month.
I don't think the OP is having trouble learning. They're having trouble with the almost-monthly changes.
Maintaining ~30 Rust applications and a few libraries at work, a handful of open-source projects, and a few embedded Rust personal projects, I didn't need to change anything at all after updating (which is the norm for most Rust releases).
In practice, the biggest things have been rustc and clippy lints starting detecting something that was either stylistically dubious or actually problematic previously existing in our codebase.
> People can push unfinished stuff in any situation.
But they don't in Rust. My example of Min Const Generics is an example of this. Async-Await (developed by GP on this thread) was also delayed to give it more time to bake.
I urge you to look at the releases page (https://github.com/rust-lang/rust/blob/master/RELEASES.md). Look at how few user facing changes are made with every release. This is a good thing! As long as you're ok with skipping these and the performance improvements, you can stay on an older release for basically forever. Most Rust libraries are conservative about their minimum supported Rust version (MSRV) so there isn't usually a push to upgrade at all.
If the OP wants a compiler and toolchain that only changes every six months, that's already available. He can stick with the same compiler for six months or even longer with 0 downsides.
> Upgrading the toolchain practically never requires any changes to code.
if you work on safety/security critical systems upgrading the toolchain is considered like changing the tires on a moving vehicle. We have introduced and many weeks later discovered critical (and hard to trace) bugs simply by changing -O2 to -O3 in gcc that ended in sporadic crashes when cross-compiling for 1 specific platform. (which is a change much less severe than upgrading gcc itself) And I'd be surprised if upgrading the toolchain wouldn't potentially introduce similar hard to trace issues in rust.
My point is that just because the first 2 months after upgrade look like there were no required changes in code doesn't mean there are none. I see rust being used in very large companies for internal projects, test harnesses, and other glue/plumbing. And the places I know are really reluctant to go all the way in and substitute their ~30 years of experience with C/C++ with something that remains a constantly moving target. To be fair there are other reasons such as culture, and distribution of skills across the team that drive these decisions but my main point still holds (i think).
I mean, even with C, there is a very circumscribed subset that you use for "safety critical" applications.
2) People are banging on about Rust not being stable but the Rust Embedded guys DO lag for stability--so you can have stability if you choose. And Rust is by far the best language I have seen about being able to stay on old compiler versions and still use newer libraries.
3) I find crappy libraries to be the biggest threat to Rust's sustainability. There was a big "Gold Rush" mentality and a whole lot of unqualified people built a whole lot of crap libraries with no good way for someone to come along later and to flag "That's a crap library, please remove it from crates.io permanently".
> changing -O2 to -O3 in gcc that ended in sporadic crashes when cross-compiling for 1 specific platform.
Sure, this happens regularly in C and C++ because large programs inevitably depend on undefined behaviour, and changing compiler versions, optimization levels and target platforms is allowed to change that behaviour.
For the last five years I've been writing 99% safe Rust code, which is designed to have no undefined behavior, and I think it's not a coincidence that I can't remember ever having a compiler update break code at runtime. Once in a long while a compiler update will fail to compile some existing code, but that's not a safety issue.
This sounds more like undefined behavior in your codebase than a compiler error. I don't know Rust but I'm pretty sure the whole selling point is that you won't run into problems like this.
There are active open bugs today in GCC and clang for x86 where optimizations can break standards-correct code [0] (writing to a union through a pointer to a currently inactive member, which std::variant does internally). For more obscure platforms and older releases, there are bound to be numerous bugs. In particular, volatile handling is notoriously shoddy on many platforms.
As an aside, the clang bug would also affect Rust if they used that type of optimization (assuming strict aliasing rules).
> As an aside, the clang bug would also affect Rust if they used that type of optimization (assuming strict aliasing rules).
No, this bug cannot affect rust, because rust wouldn't allow to pass into a function three mutable references pointing to the same object. It wouldn't even allow two, nor one mutable and one immutable. Either it pass one mutable reference, or any number of immutable.
Not sure if that bug explicitly, but the fact that clang in noalias mode assumes that two pointers to different variants of the same union are not aliased (if it can't see from the immediate context that they are pointers to the same union variable) can very much affect Rust - if you call one function with a &mut to one field, than another function with a &mut to another field, and the optimizer inlines both functions in a broader context and loses the union information, you may well see reordering issues even in pure safe Rust.
Anyway, Rust has found plenty of noalias bugs in clang, which is why it still doesn't compile with noalias optimizations turned on.
That somehow rapid-release is antithetical to the enterprise is a very archaic view of enterprise computing. Enterprises use cloud HR software, Office suites (MS365 and Google Workspace), Salesforce, etc all the time and those update on a fairly frequent basis. Also, given the need to patch promptly, most forward-looking enterprises have much more responsive systems in place -- including investments in good CI/CD systems to deliver even internal software faster. So they're quite comfortable with the "new normal" of the software industry.
The most used enterprise OS, Windows, is rapid release too -- every 6 months, coincidentally! But there's a LTSB branch you can use. Java releases every 6 months too, and that hasn't halted enterprise adoption. Similarly with C#, not every team jumps to the latest language level just because it was released. Teams should pick language updates at a speed that suits them -- but hopefully not so slowly that moving to newer releases becomes difficult.
Similarly with Go. Why should it be any different with Rust? To the extent that enterprises are using the latter two in massive numbers. The key thing is, as others have noted, is stability and a lack of breaking changes.
>with C#, not every team jumps to the latest language level just because it was released.
Exactly when it comes to Java, even though there is now a 6 month release cadence, take a survey of which version most are using. Certainly every time I bring this up, someone pops up and says, "I'm using 11" or "10". But the vast majority of "enterprises" are at max, Java 8. And they'll remain on 8 until something forces them off of it. Enterprises by nature move at a glacial pace. So their reason for adopting Java is not because it's "moving fast".
> So their reason for adopting Java is not because it's "moving fast".
I was replying to the parent poster, who said that moving fast is a roadblock to enterprise adoption. Whether enterprises adopt Java because it's moving fast is another question altogether. Certainly no one is deserting Java because of the decision to boost its release cadence.
> Enterprises by nature move at a glacial pace
I think it depends on the enterprise.[1]
Cyber-Security has changed the game for many enterprises very fundamentally. Well-run enterprises now patch more promptly than many consumers -- at least, certainly the consumers who don't auto-update. Well, unless they want a Maersk-like incident[2], or be infected by ransomware. Maersk's incident cost it $200M if you believe Forbes.
About slow JVM upgrades, a lot of that is a cost/benefit calculation or poor technical leadership. CIOs and COOs (or audit, for that matter) have no interest in which Java version you use. The only questions are: Is it secure? Does it make commercial sense?
For actively developed software, staying on a recent-ish Java isn't a problem (many good enterprises have adopted Devops in some shape and form -- just add a task to your CI server to test on the latest JRE) once your engineering team has crossed the Java 8-to-11 hump. If you do that, you get to not pay Oracle $$$ per desktop/server every year (or you could use Corretto etc, but most enterprises will choose to pay Oracle). Or you could simply upgrade for the productivity & JVM improvements.
Legacy products not in active development are another matter, but even there -- the cost of not getting security updates is too high nowadays, so you have to spend money to secure it -- and legacy software has other costs too[3]. So unless you're a developer working on a legacy app, or an app who's design is so poor that it's locked into Java 8, there's no reason you couldn't be on Java 11 soon and get on the rapid cadence train yourself thereafter. It's really about how nimble your team is.
Of course, you could be unfortunate enough to work in an enterprise that doesn't take cyber-security seriously, in which case YOLO.
I've come to dislike versioning stuff more and more. It's an invitation for people to get stuck on a version. And as time goes on it becomes harder to upgrade to the latest version so the trap continues to tighten. Enterprisey stuff should choose things that prioritize backwards compatibility and well tested changes. Settling on a LTS version seems attractive but it's a trap and should be avoided.
> If the OP wants a compiler and toolchain that only changes every six months, that's already available. He can stick with the same compiler for six months or even longer with 0 downsides.
Sure, but there's also things like how long will the current version be supported if there are security issues, or similar. People also want a version that will be supported with bug/security fixes for 6 or 12 months vs "Oh it's broken? Upgrade to head."
> > Features that haven't been fully baked would be pushed in to the current release because people wouldn't want to wait another 6 months to see their work come to fruition.
> This psychological tinkering isn't helpful.
The former comment is thoughtfulness about the ways that a system of work influences contributors mindset and thereby project quality. Even if the specific conclusion was incorrect, the earnest attempt is necessary to project health. If you disagree, you probably want to short-sell Toyota stock.
I was at Mozilla when we switched from 3-to-6-monthly releases to 6-weekly releases. It really was an enormous positive improvement.
> you can close it off 5 months in and then stabilise for a month.
This doesn't help. If a release happens every six months then regardless of what you do during the release cycle, you are faced with situations where someone has a work item just about ready to ship in release X, but not quite, and you face enormous pressure to ship it in release X rather than in release X+1 six months later. On the flip side if you do force it to slip to release X+1 then that's several months of users not having the benefit even though it's ready.
If you're releasing every six weeks, there isn't any such pressure. Less work is shipped prematurely, less work is shipped later than necessary, and developers are less stressed.
At the company I worked at right now we went from releasing every sprint at a specific release window. To lets release whenever we want because we have some blue-green support.
And it has been a game changer if you ask me, Jira tickets don't pile up in the test lane, testers don't have to do one big regression tests at the end of the sprint just to sure. Sometimes even making them work overtime just to be sure. The code area that introduced new bugs is way smaller and the bugs have become easier to trace down.
>Features that haven't been fully baked would be pushed in to the current release because people wouldn't want to wait another 6 months to see their work come to fruition.
Only if Rust has an awful leadership team organizing those releases. Strong leadership and careful release planning nips this right in the bud. "Your feature was only 'finished' a week ago? No way in hell is it making the release. See you in six months."
The other view is that shipping less frequently encourages features to be shipped fully baked and matured, with plenty of time for careful thought and attention given to their design and implementation.
The point is, you build a process that encourages the outcome you want. A six-week release cycle makes it easier to do the right thing. Even with the six week cycle, we do this, with const generics being the latest example. But it's much, much easier to say "hey it's just six more weeks" than "hey it's just three more years," not just on the folks making the decision, but on the folks doing the work, and on the folks excited to use the feature.
> shipping less frequently encourages features to be shipped fully baked and matured,
Right, but this is just a view. A significant part of the industry believes that shipping less frequently discourages this. We've found that shipping more frequently allows us to take our time and fully bake and mature features in Rust.
> Regular releases of the compiler are awesome for the same reason continuous deployment of web apps is - each release only packs a small number of features.
Developing a compiler for a complex language is very different from developing a webapp.
It sure is, but do you have any substantial reason to say why that would invalidate the point they are saying, "each release only packs a small number of features"?
over-engineering in hope that the language does everything for everybody is my biggest worry and why my excitement to consider it as something I want to work with drops with every year. Considering how quickly the language evolves (which ought to be a good thing considering it's still new) I'm being put off by all these features that only few need, while at the same time things like async are broken by design (not to mention the opinionated tooling of cargo, rustup, etc that follow the same flawed principles as npm, rvm and even cpan).
Perhaps I'm being too conservative but I'd have more trust in the language if things were moving slower especially that rust positions itself as a systems programming language fit for production (today). Which is odd because what I want from something that ticks these 2 boxes is interface stability. I have more confidence in Zig or Nim for this reason. Give it another 5 years and it will be a similar mess as C++, or worse: Python (which ended up rolling out v3 which wasn't backward compatible with v2). Also the "safety/security" argument which is their big selling-point which goes out the window as soon as you pull 3rd party crates (as is the case in most of the projects).
Suggesting that Rust will follow Python by forking the language incompatibly is completely unfounded. No-one has shown any interest in that, and the edition system was designed specifically to avoid any need for that.
> Also the "safety/security" argument which is their big selling-point which goes out the window as soon as you pull 3rd party crates
Not at all. Rust's safety guarantees work in practice. In years working on our largish Rust project we practically never have had to deal with memory corruption or data races.
> Not at all. Rust's safety guarantees work in practice.
They don't just work in practice. I spent 3 months last semester being taught in the separation logic "Iris", which is used to formally prove the safety guarantees of Rust as part of the RustBelt[0] project. That was under Lars Birkedal, for anyone curious.
Rust is a language I love doing actual work in, but it's also one I really like from the perspective of the theoretical backing.
It doesn't really matter to me what you, an internet stranger, are "excited to consider as something you want to work with." Instead, what you should consider is how incredibly boorish it is to post that "async is broken by design" in reply to the person who designed async.
I’m not sure why “rust async bad” has become a meme lately. I think people who don’t know much about rust need something to put it down and async is just an easy target. I’ve been using rust professionally for 3 years now and think async is great, and certainly has come a long way. I think there’s some work around closures that could be made better (explicit lifetimes, matching, etc) and some ecosystem fragmentation (Tokio, async-std) but I’m sure everything will settle out in due time. Thanks for contributing - don’t let internet people get you down.
That's, uh, a rather bold assertion. Perhaps you could elaborate on why you feel it's "broken by design"? I've never heard anyone take that position at all, much less make an implied claim that it's a widely-accepted position.
> I have more confidence in Zig or Nim for this reason
Do you realize that at this point Rust is way more stable than those two languages? It's not a critique at all as they are much younger, but these are really bad examples to compare with.
The first public release of Nim was June, 2008, but work began a few years earlier. So, Nim is at least a couple or more years older than Rust. Stability is often subjective (in terms of features people actually use).
This is just a report of the voices of the people I'm converting to Rust because they are never heard.
The compound effect of small and fast changes is complexity.
Uncontrolled complexity is the thing we want to avoid as it's fatal to any project.
Yes there are editions. But from a newcomer's point of view they only add complexity.
I'm convinced that short release cycle and feature 'bloat' are related. I simply don't want Rust to become the new C++ (which is the feeling of a lot of people).
My opinion (programming with Rust since May 2015): Rust is complex but 2020 I discovered that in «This week in Rust» [0] many weeks pass with the section
New RFCs
No new RFCs were proposed this week
This shows that the rapid pace of change already started to slow.
The new C++ is unquestionably preferred to the old C++ (when nothing was standard or built in, everybody spent ages trying to build Boost, and so on).
Software development / computer programming is complex. Hiding complexity is bad. News at 11. /s
So, that said newcomers are free to pick their poison regarding tech stack, language, etc. They can use something simple, easy, friendly, and sort of self-contained. Let's say Ruby on Rails, Django, or C# stuff. Inevitably they'll very soon run into the problem of managing dependencies, platforms, native code, security considerations, performance issues, etc.
> I'm convinced that short release cycle and feature 'bloat' are related. I simply don't want Rust to become the new C++
I'm confused... C++ doesn't have a short release cycle and it became feature bloated, so how did that lead you to conclude that the short release cycle of Rust is causing Rust to become feature bloated like C++?
> I'm convinced that short release cycle and feature 'bloat' are related. I simply don't want Rust to become the new C++ (which is the feeling of a lot of people).
Most of the problems with C++ come from the long release cycle and cause the bloat you're talking about. C++ rushes out unfinished features (see std::visit for a great example) to make a release window resulting in unfinished half working features that are horrible to use full of footguns.
That may be true, but there are already discussions about revisiting some already-implemented features - e.g. Async (https://blog.rust-lang.org/2021/03/18/async-vision-doc.html). So I'm not really optimistic that the pace of changes will slow down significantly...
I read the post you linked and it doesn't seem to say that at all... it's about how async can be improved in general, not revisiting existing features.
I've actually found Rust to be extremely stable since I started using it 5-ish years ago. I haven't had as much time to keep up with new features recently, but all my old code still builds as easily as it always did and the way I used to write code still works fine. I don't imagine I'm missing anything huge and transformative, and I tend to find new-to-me features on an as-needed basis through docs and web search.
It is kind of annoying when big libraries that are generally touted as the way to do X require nightly, but again that's my experience as of years ago. Nightly should be understood as a place where churn happens. For me, stable releases have never been anything but what it says on the tin.
I think Rust's biggest threat is that it's repeating the same mistakes C++ did, despite the hindsight. C++ tried to be everything for everyone -- a language elaborate enough to write applications in a style that appears high-level on the page, and yet not give up on the full control required for low-level programming. For a while, it worked. The problems only became apparent some years later, when large applications had to be maintained, and people realised that low-level languages, no matter how high-level-looking, all make a certain sacrifice: low abstraction. Clients of components are sensitive to implementation details of those components, and so the maintenance of applications costs as much as that of low-level code does. OTOH, the complexity of the language made portability hard (low-level code is often written for custom hardware) and also hard to analyse. C continued to dominate the embedded space, the application space went to true high-level languages, and C++ kept an intermediate, though important niche, of games and software platforms for capable-enough hardware, which it firmly holds on to.
Rust is now doing the same. Few in the embedded space find it appealing, many of those who use C++ do (as it is certainly a cleaned-up C++, and a nice improvement in comparison), but too often not appealing enough to switch now, and some in the application space who don't know or don't remember the C++ lesson do adopt it now (sometimes out of sheer novelty) but will likely abandon it later for similar reasons C++ was largely abandoned in that space. So it is really competing for a pretty small and conservative niche -- albeit an important one -- and one with a strong incumbent. If it does very well, in 20 years we might find that 60% of the C++ space has switched over to Rust, and that's about it.
What Rust needs is focus, but it won't have it because I think some of its designers still believe in what C++ believed. That you can have a language that is both high-level and low-level, with the benefits of both and the downsides of neither.So it's being pulled in multiple directions, all while showing poor performance in the market (C++, at least, wasn't just hyped but actually popular). It's not even going after C++'s market seriously, but after the nonexistent market C++ thought it could occupy; the only market it seems to be actually competing over and doing well in is HN-front-page real-estate, the space formerly occupied by Ruby and Haskell. When I was at University in the late '90s, everyone was talking about Haskell will be the language of the future. With almost constant levels of hype, more than twenty years later, it still is. It turns out that for various reasons, when it comes to programming languages, hype and market performance can be completely out of sync for decades. Rust's designers need to choose between adoration and actual popularity. The latter will require some tough decisions. If it's going after the C++ market, it should make itself extremely appealing, irresistibly so, to C++ programmers.
I have no idea what Zig might turn up to be. I like it a lot aesthetically, but it's far too early to tell what market adoption, if any, it will see. But at least its strategy is clearer: it ignores the (incidental?) "C++ niche" altogether, and says that there are only two categories, low and high, and it's going after low. This covers all of C and the majority (>75%) of the C++ space.
I definitely don't get the feeling that C++ was that popular, I distintcly remember many Linus rants about it. It's just that after years of usage it carved its own niche.
However one pain point Rust does address is parallelism. If you want to use modern systems, and you're going with C++. Good luck. You're gonna need it.
As for the popularity, I think that's moot. But I do agree Rust can't be everything to everyone. One problem it will have for the forseable future, is the slow compile speed. But on the flip side, Rust has been super popular.
But it does one thing no other language does. Safe concurrency without GC. It's like a seatbelt in a car. Once you get used to it, you'll be paranoid its not there.
----
Where I do agree with article author was rate of change. IMO Pin should have never been added to standard library as it currently is. But async was rushed, for god knows what reasons.
They could have said "we won't ship this yet," and they also could have said "ship it" to the initial design in 2015.
> took a more principled stance
This is very insulting. Bugs are often found in every kind of software. Virtually no languages that exist, let alone popular ones, require proofs before landing new features.
> This is very insulting. Bugs are often found in every kind of software.
To me it's not a bug. It's a foundational flaw. If Rust was a house, and a bug was a broken window, unsoundness issue would be water seeping into the foundation.
If standard library is unsound, that means pretty much everything derived from/relying on that functionality is unsound.
Adding unsoundness for the sake of pushing a feature out is just bad. It's cutting corners on essential things.
> they also could have said "ship it"
True. But if I know that BDFL is an asshat, then I avoid that project.
There is a difference between saying "I believe new features should have proofs of soundness before landing" and saying that developers are "unprincipled." The former is a specific technical critique, the latter is an insult directed at the people making decisions. Specific technical critiques are great. Suggesting a lack of principle from the developers is not.
Here's why this matters. This response from you is much better! Because:
> If Rust was a house, and a bug was a broken window, unsoundness issue would be water seeping into the foundation.
Yes. Everyone agrees, in principle, that Rust being sound is an important property. Your criticism isn't actually about principles, it (appears to me, anyway) that it is about the specific methods in which we figure out if something is sound or not. You can argue that nothing should be added without formal proof, and that's a fine position to take, but at least it is a specific, actionable criticism that can be discussed directly.
By this standard, virtually all languages have "unprincipled" designers. This isn't even true of only async! We didn't (and still sort of don't) have a formal model of the borrow checker. So you can't really criticize async specifically in this way, you'd have to criticize the entire language.
> the latter is an insult directed at the people making decisions
The way I see unprincipled is two fold:
1) You're breaking your promise
2) In a similar situation behave differently
1) Pin was a problem from the start. Allowing it into std/core was a mistake. The fact they allowed an almost blatantly unsound feature is unprincipled.
I'm not 100% sure of the timeline, but near or before the release there were examples floating of a possible Pin unsoundness. And defense was, it's an obscure thing, no one would really use that in practice. The moment designer says, no one would use that in practice, is the moment they lost.
2)
Yeah, I get async was a feature everyone wanted. By same measure, why not add self-referential struct. People want it. It's probably unsound but you can't tell. Maybe there exist a model that allows self-referntial structs.
Nobody promised full formal specifications before landing features. The pin soundness issue was found close to release, but a plan was made to fix it before it was released. Pin is not fundamentally unsound.
People do want it, and in fact, it is part of async, and directly related to the soundness issues you’re complaint about. The reason such things aren’t in stable is that, while people do want it, people wanted async more, and did the work. The work has to happen, features don’t just magically come into existence.
Linus wanted attention and C++ was perfect. Later down the road, he even ranted about Java. It's clear he is a hater of OOP and Abstraction in general. Now, Linus Cultists promotes Data Oriented Design.
The attention thing said by Bjarne by himself when asked on Reddit.
> I think Rust's biggest threat is that it's repeating the same mistakes C++ did, despite the hindsight. C++ tried to be everything for everyone -- a language elaborate enough to write applications in a style that appears high-level on the page, and yet not give up on the full control required for low-level programming. For a while, it worked.
... and... doesn't it still work ? An awful lot of C++ applications are being written today, and that can be done at a pretty high abstraction level thanks to the type-level facilities of C++.
> . Few in the embedded space find it appealing, many of those who use C++ do (as it is certainly a cleaned-up C++, and a nice improvement in comparison), but too often not appealing enough to switch now, and some in the application space who don't know or don't remember the C++ lesson do adopt it now (sometimes out of sheer novelty) but will likely abandon it later for similar reasons C++ was largely abandoned in that space.
are we talking about the same embedded? most C shop migrate to C++. most car brands, and a lot of appliances, use Qt for their UI (C++)
> C++ is nowhere near as dominant in that space as it was in the early nineties.
You’re rewriting history here, friend.
Hardly anyone was writing embedded C++ in the 90s. Even nowadays I bump elbows with Developers that refuse to make the move from C in embedded.
If we’re talking Desktop apps, well... yeah, Windows was the new hotness, OOP was hot ‘n fresh, and Visual C++ was a BFD. Once more languages came about, people found ones they preferred over C++ (Java was a BFD).
As to your last comment, I’m guessing you haven’t worked in the embedded space with C++ if that is your conclusion
> Hardly anyone was writing embedded C++ in the 90s.
I wasn't talking about embedded in that section, but about applications, and not just desktop.
> Once more languages came about, people found ones they preferred over C++
High-level languages were used a lot before, like VB and other RAD languages. But the belief was that they'd be too slow for many applications, like servers.
> As to your last comment, I’m guessing you haven’t worked in the embedded space with C++ if that is your conclusion
That is correct, and yet the lower the hardware capabilities and the higher the required safety, you see more C and less C++.
I've done my share of C++ and now Rust, and I don't really get why people keep saying that Rust is a 'cleaned-up C++'. In my opinion this couldn't be further from my subjective truth. I see C++ as an effort to extend C to enable object oriented programming patterns. And everything else being added to it as more and more people have come to appreciate patterns from other programming paradigms. But fundamentally C++ to me is still 'C with classes'.
Whereas Rust, to me at least, is 'ML-ish with curly braces'. So, a language firmly based in the ML heritage with C-like syntax. So, fundamentally working with types and 'typeclasses' and heavily leaning towards filter/map/fold/reduce/lift/unlift type of thinking. Sure, throwing funtions around as first class objects are not as easy or straightforward as it is in 'real FP' languages, but that's a trade-off I'm willing to take for the guarantees that Rust provides.
I'm genuinely curious what's the reasoning behind being able to assert that 'Rust is a cleaned-up C++'.
You're doing the comparison from the bottom-up, perhaps like how a programming language connoisseur would look at them -- how the linguistic features of C++ and Rust were constructed -- while I'm looking at them from the top down, how just a programmer who doesn't particularly care about PL theory would: what is their design philosophy? Both are low-level languages (so, low-abstraction), which try hard through various syntactical techniques and a nice dose of implicitness to make code, once written, appear high-level on the page. I find those two languages almost indistinguishable in terms of "feel." It doesn't feel like Python, it doesn't feel like Java or Go, and it doesn't feel like C; it feels like C++.
I do agree that Rust 'feels' more like C++ than Python or Java. But then, from my limited experience with dabbling into Haskell, to me it feels more like Haskell than C++. In Rust, from the language perspective, I have to deal with things like these:
- Doing Option<T> -> Option<U>
- At what point do I do Option<T> -> Result<T>
- Should I transpose Vec<Option<T>> to Option<Vec<T>> now or later?
- Often reaching for algebraic data types
- How to map over this to collect it into what I need
- Ah, it needs to implement Hash, Eq, PartialEq ... SomeTrait to make it work the way I want
- Pattern matching all over the place
All of which to me mentally feels more like something along the lines of F#, OCaml or Haskell than C++ that 'normal people write'.
Have you not seen much modern C++? If you are used to this style of C++, Rust is a very obvious variant of it, but with more static guarantees with regards to safety. Working heavily with types has been common in C++ for a couple decades now, and there are libraries with bring in filter/map/fold/reduce/lift/unlift style.
The code I've had to work with was definitely more on the OOP paradigm side. Can you provide an example project with a more 'modern' C++ code base that I could check out?
Rust is rather more like "Haskell-ish C++". (Typeclasses were popularized by Haskell and are not available in SML or OCaml.) While the C++ heritage is obviously the memory management – no runtime, heavy use of scope based deterministic destruction ("RAII"). Also the compile-time metaprogramming that gets monomorphized. (All those template/generic instantiations that can bloat the binaries if overused :D)
I've been bashed before for saying something along the lines of "Haskell-ish C++". Their fair point being that the only Haskell influence is the typeclasses, and all other ML-influences are just ML-influences that are not unique to Haskell. Fair enough :)
(As an aside, WOW! What a great invention! The folks who sent in pictures of their tiny cuts (instead of severed fingers) nearly made me cry.)
That's a brilliant metaphor to drive home the safety advantages of Rust! "It's a table saw that won't chop off your fingers!"
That's a "shut up and take my money" proposition. (And it helps that it's a really good table saw too.)
(As another aside, I got to the testimonial from an employer talking about the peace of mind of knowing the workers on the shop floor are safe and it "clicked" for me: you've got metrics and liability for job site safety so you can quantify that peace of mind. We still not there with software quality liability eh?)
One of the things I often see in Rust is comparisons with C++
"It's simpler than C++!". Yeah, Rust could become a bloated mess and still be simpler than C++. It's like saying that a mountain is not high because it's smaller than the Everest. It's not a good idea to use C++ as reference.
I don't think it is contentious at all to say that C++, Ada, and Rust are all in the top five most complex languages in the history of software. All three tried to be low-level languages that appear high-level.
Complex is a poor adjective to talk about Rust: Rust is hard because there's one key concept one must learn before doing anything: ownership. And this concept (at least in the Rust incarnation) is completely alien, so you need to unlearn how to code before re-learning it the Rust way. This is hard and that's why Rust have a tough learning curve.
But Rust isn't complex: there aren't many features interacting in a special way with one another with a combinatorial explosion of interactions you need to know in order not to shoot yourself in the foot. (Move semantic difference between Rust and C++ are a good illustration of that).
Actually, in terms of number of different features you'll encounter when onboarding a new project, Rust is far behind JavaScript and PHP (PHP being the biggest example of how feature bloat doesn't kill a language, even if your language is targeted at inexperienced developers).
In absence of good metrics for the kind of complexity we're trying to discuss I think we kind of have to rely on these sorts of first-person subjective reports from the field.
There is a valid point here, which is that it's sometimes difficult to know what "the right thing to do" is in Rust, because it is a large language. I agree and can sympathize. I happen to like Zig also, FWIW.
But it does need to be said, that the approach he was using with Rust was absolutely not the right tool for the job. The author should have been using traits. That's what they're for, and they definitely aren't an obscure language feature.
This article has been extensively discussed here and on reddit, the authors faced a problem, did not seek help, and solved on his own it in a pretty convoluted way involving compile-time metaprogramming with macros. As pointed elsewhere, his problem is usually addressed using the type system (enums or traits). You can write a non-standard over-engineered solution to a problem with any programming language, that doesn't mean the language is complex. Zig being especially designed around compile-time meta-programming, it's not a surprise that the resulting code looks much more straightforward.
And that being said, the author mainly complains about features that also exist in C (macros and ifdef, and Rust's version are easier than the C one), would you call C a too complex language because it has macros and ifdef? (I actually think that C is one of the most complex programming language ever written because you need to store too much invariants in your head otherwise it's UB, but ifdef and macros aren't at stake )
You (and dralley) are missing the point: the dude made a wrong turn with Rust and didn't with Zig. You can blame the user all day long but at the end of the day what leverage Rust devs have is not in the user's head, eh?
- - - -
> I actually think that C is one of the most complex programming language ever written because you need to store too much invariants in your head otherwise it's UB, but ifdef and macros aren't at stake
Like I said, without metrics we're just trading subjective anecdotes.
Metrics for complexity of machines is a subject I find fascinating, ever since I read Ashby's "Introduction to Cybernetics" wherein he asks the question "How can we measure the complexity of a machine?" in the context of a formal system for describing machines (Cybernetics.)
> the dude made a wrong turn with Rust and didn't with Zig.
Yes, this one guy made a wrong turn once. If you want to conclude from one user making a mistake that a language is complex then you're just going to conclude that programming is complex … Everyday, with every language under the sun, people make mistakes, great discovery.
I'm not blaming “the user®” here, I'm blaming the blog post writer who makes a mistake and concludes that his tool is responsible for it and that he should tell the world how bad the tool is.
> Like I said, without metrics we're just trading subjective anecdotes.
Well that sentence is pretty ironic given the previous one, nevermind.
> We could compare the sizes of compilers for C and Rust.
I wonder what conclusion you'd draw from such a comparison. That assembly is the least complex language in existence, followed by Brainfuck and Chicken?
> We could teach each to different randomized groups of students and see how quickly people learn to write (safe!) code in each.
Oh I actually like this one. For Rust, you'd need to run a study to find out, but for C the answer is trivial: Never. Nobody on earth know how to write safe C. Not even DJB, not even Theo de Raadt, or Richard Hipp, or Brad Spengler. For almost 50 years, the brightest minds of computer science have tried to write safe C code, and consistently failed. Can we conclude that this language is a little bit too complex for humans, or should we wait a few decades more?
What I'd like is the ability to slowly switch newer parts of the codebase from C++ to Rust, with seamless interop between the two languages(IDE/Debugger/Profiler), but this is likely a pipe dream, and without this capability I doubt I'll be switching to Rust.
> Rust's designers need to choose between adoration and actual popularity. The latter will require some tough decisions. If it's going after the C++ market, it should make itself extremely appealing, irresistibly so, to C++ programmers.
And what decisions would that be? Your post seems self contradictory to me because it implies that Rust is both too "low abstraction" to be "extremely appealing" to C++ crowd, and too complex and "hard to analyze" to displace C in use-cases that require portability and/or are resource constrained.
I didn't say it's too low abstraction to appeal to C++ programmers; Rust and C++ (and Ada, and Zig) have the same level of abstraction. I'm saying that Rust should seriously fight for the market C++ was able to actually carve out, rather than the market C++ dreamed it could have when it first gained traction. Doubly so because Rust is starting at a disadvantage compared to what C++ had: C++ already exists, and many people already know that a language that looks high-level but isn't, doesn't have the same maintenance costs as actual high-level languages. If it doesn't focus, what will happen is that it won't capture enough C++ people, and instead, it will get many people who didn't learn C++'s lesson, who will use Rust for some years and then abandon it -- just as happened to C++ -- and then it will be left with not much; it will have too little of the C++ market and too little of the applications market.
If there's anything we can learn from programming languages -- be they C, C++, Ruby, PHP, Haskell, or Java -- riding the hype-train led by PL enthusiasts and early-adopters is not a good recipe for long-term success (even if it is a good recipe for long-term hype). Like with fashion (and I think HN is more like GQ or Vogue than actual industry news; i.e. it is more aspirational and inspirational than descriptive or prescriptive), the languages people talk about and those they actually use for many years are usually not the same.
> I'm saying that Rust should seriously fight for the market C++ was able to actually carve out, rather than the market C++ dreamed it could have when it first gained traction
That's exactly what Rust is doing. It used to have a runtime, green threads and a GC, but it doesn't because that's not what C++ developers want. And recent development work has been focussed on const generics and const fn which are both keys things seen as missing by C++ developers.
What exactly do you mean by making "tough decisions", "fight for the market" and "make itself extremely appealing"? I've just re-read both of you messages in this thread and didn't find any single specific technical suggestion.
That's because I don't know how to do that, and it might not be purely technical. But what Rust is doing doesn't seem to be working. Six years since 1.0 and almost unheard-of levels of hype, market penetration isn't even at 0.1%. It's a language with Python-level coverage and Elixir-level adoption.
Well, yes, of course. Rust is not made by Apple, MS or Google who can just make it new "official" language on their platform and force adoption. Also, by its very nature (low-level-ish language without GC) it cannot have Python-level adoption in modern software development ecosystem.
Why would you want Rust to target lowest-common-denominator developers and become new VB or php? All it needs is enough momentum to become self-sufficient, which seems to be actually happening now with Rust Foundation and news of its usage in some major companies that can set the trends for whole industry (Amazon, Google, etc.).
From the perspective of someone who's been writing Rust professionally for the last few years, the hockey-stick curve started kicking in in late 2020 or so.
Well, do you have evidence to support your claim that penetration is <0.1%? My impression is that it's simply not true now that most (if not all) of the FAANGs have many developers using it.
But you can even have a rough estimate according to your own measure. There are roughly between 50K and 100K developers working at FAANG (maybe replace Netflix with Microsoft). How many of them would you guess are using Rust?
Could you please make specific claims here? Arguments that don't provide any examples are generally worse than useless.
I don't think Rust and C++ have the same level of abstraction, for example. Rust has ADTs and pattern matching, C++ only has product types and std::variant.
Abstraction doesn't mean syntactic constructs. It means the ability to specify arbitrary aspects of behaviour and then provide interchangeable implementations of the behaviour. When abstractions can have more satisfying implementations, you have high abstraction; when they have less you have low abstraction (i.e. you can abstract only smaller groups of things). Replacing, say, a concrete type with a trait is about as much work in Rust as it is in Assembly. It's not a feature of Rust specifically, but of low-level programming. If you want control over object layout, placement, and lifetime, it means that you abstract over things with specific low-level details, so fewer things. This isn't a problem, but a tradeoff that low-level programming intentionally makes, that no syntax can erase.
Yes and no. Let's drill down into this because the details are important.
There's a crucial distinction between input and output types in practice. For a given input type T, Rust makes it possible to abstract over `T`, `&T`, `Cow<'a, T>`, `Arc<T>` etc, by using a trait such as `impl AsRef<T>`.
However, Rust doesn't currently have existential types, so its ability to abstract over output types is more limited. You can implement, for example, `fn foo(&self) -> impl AsRef<T> + '_`, but you can't name that type. So if you want to return an enum, you can't write
Instead, you have to concretize the type somehow, either by boxing things up into a trait object (often but not always possible) or by exposing the generic param:
This is a real problem, though one that will be solved through existential types.
> Replacing, say, a concrete type with a trait is about as much work in Rust as it is in Assembly.
I'm not sure what you mean here. I'm not aware of any assembly languages which have traits. Replacing a concrete type with a trait tends to be pretty easy in Rust because mistakes are caught at compile time.
I agree that existential types can increase the abstraction level, but not to the level of high-level languages (and they increase generated code-size), because in the end there are still specific low-level details a lot of code needs to care about, like storage and lifetime.
> I'm not aware of any assembly languages which have traits. Replacing a concrete type with a trait tends to be pretty easy in Rust because mistakes are caught at compile time.
I'm not thinking in terms of language features but abstractions. The best way to see this is to think how many different implementations to a code unit I can do without making the consumer aware? That number is significantly lower for low-level languages compared to high-level languages because things that can be hidden in high-level languages, like layout, storage and lifetime, must not be in low-level ones, hence "low abstraction." Changing something in one place is more likely to require changes elsewhere. Therefore, low-level programs are more rigid, more jigsaw-like, and their evolution more difficult.
It is true that a compiler that tells you if you missed a change helps a lot, but it doesn't change the nature of the low-level language, even though it improves its ergonomics (although it's not so simple, as sometimes even correct programs are rejected) -- you still need to do all the extra work, but it doesn't take quite as long.
> For a while, it worked. The problems only became apparent some years later, when large applications had to be maintained, and people realised that low-level languages, no matter how high-level-looking, all make a certain sacrifice: low abstraction.
Not really; Rust is very careful to avoid leaky abstractions, compared to C++. It's definitely "low level" in a foundational sense (even reminiscent of C in many ways) but the limited "high-level" features it does have are incredibly solid and highly usable.
For a given abstraction, think API, the number of correct implementations in Rust, C++, C and Assembly is roughly the same, and it is much lower than the number of correct implementations in, say, Python. That's what "low abstraction" means. The abstraction can be very precise with a rich type system like Rust's, but that doesn't make it any wider. This means that clients are just as sensitive to changes in implementation details, and that the cost of maintenance is high relative to high-level languages, even though the type checker can find the mistakes and tell you that the considerable work you may have to do is not done.
GPGPU, game engines middleware, and compiler research using LLVM have rejuvenated C++.
Additionally at least on Windows, Microsoft still believes in C++ for doing the kind of desktop applications you are talking about.
All these scenarios aren't properly covered by Rust in its current state, even the Rust/WinRT project is doing baby steps, very far away from what VC++ offers today.
Rust occupies a place that as a c++ developer is interesting. When someone says Ruby I think Python is good enough, I don't write a lot of the type of code where it is useful.
Haskell doesn't promise the type of control I need. Someone i work with rewrote our main control algorithm and proved it was correct (not in Haskell ,I just fear this problem ), but it took over a minute to run, and this PID loop needs to run at 5hz and leave some processor for other tasks. My c++ isn't proven correct but we have 15 years of production with it.
Rust promises to avoid some of the things we don't like about c++ while still worming in the real world. So of course I'm interested.
For me the biggest problem with Rust is its so darn complex. I recently had to modernise a few ancient CLI tools and knew it was a case of Rust vs Go.
I knew neither language, but try as I might I just could never get going with Rust. The syntax is obscure, the concepts are complex. There is also no real IDE for Rust.
Meanwhile Go was much quicker to get working code with, and when combined with the excellent Jetbrains GoLand IDE, my initial spaghetti code was soon transformed into a cleaner and maintainable format. The Go community on Slack is also a great resource.
The official CLion plugin for Rust is phenomenal, and almost feels like a first class IDE nowadays.
I appreciate Rust is more complex than other languages and much less easier to pick up and learn on the job though. It definitely takes a lot of practice to get to the point where traits/lifetimes/ownership etc feel like brilliant tools rather than needless complexity.
This comment echoes a common sentiment of Rust and Go somehow being in the same category (maybe because of the "systems programming language" buzzphrase) but they're really not.
Comparing a language with a fairly significant runtime and garbage collection to a language with basically no runtime and strict (albeit largely automated) compile-time memory management is comparing chalk and cheese. You might as well say "I tried C++ but ended up going with Python because it was quicker to code" -- of course it was!
I don't think we should dismiss these comments so eagerly. Take a look at Nim - it's fast, efficient and elegant without the huge syntax overhead of Rust.
I'm not an expert in Nim, so it would be great if others could jump in. But to my understanding, Nim's ORC "garbage collector" (I'd rather call it memory strategy) is very similar to Rust's approach, it's based on reference counting (RC). It can also handle cyclic references.
It is not at all like Rust; it is a garbage collection system based on reference counting, pretty similar to Swift. This is obscured by the documentation for each using similar terminology (like "move semantics" and "ownership") to refer to systems with different characteristics.
Thanks for clarification withoutboats2!
It's really confusing as Nim's move semantics "feel" very similar to Rust's (except that Nim is more relaxed regarding "use after move" - it simply performs a copy). I'll need to learn a lot more about the different concepts.
If the desideratum is "I want a decently fast language that compiles to standalone binaries", which would be normal for CLI tools, then they certainly are in the running against each other. Having a runtime or a GC isn't that important of a consideration for most software I would think.
To me, the sentiment seems to be that Rust is explicitly tailored for code that cares about no runtime overhead. If you don't have those requirements, then don't use Rust.
This is why I reach for Go by default when writing CLI tools. You will get your job done faster, and it will be much easier to understand and maintain. You will be trading off many of the static guarantees that Rust gives, but it's worth it for CLI tools, most of the time.
If you are writing code with strict performance requirements, then consider Rust. Otherwise you'll likely be adding a whole bunch of complexity for not much gain, and your code will require much more cognitive overhead to understand and contribute to.
If only Crystal has full windows support, then I can confidently recommend it to you.
Building cli tools in crystal is fairly easy thank to the standard OptionParser library. `colorize` is almost perfect, too, in case you want to print some ascii colors.
And just like ruby, invoking some shell command is simply wrapping the command with backticks. and FileUtils has ton of features.
This is a blog post which could really do with examples. What kinds of changes and features are causing them anxiety about their code becoming 'obselete'? My experience is Rust is not changing very fast, maybe one of the release notes are of interest to me, and they are mostly 'oh, that's nice to have', not 'I must immediately rewrite all the code which could use this'.
While I appreciate the fast moving pace, I have to admit that it is hurting two big things:
* long term support
* choice, in particular in building shared libraries.
While a lot can be argued on the first point, the community seems to be actively against anyone who wants to use or build stuff with shared libraries. Shared libs are extremely useful in resource constrained environments like routers, and the debate on who should update things (distro maintainers vs project maintainers) is still very well out there.
But breaking compatibility every compiler release is a huge pain the butt, and will force those who need shared libs for one reason or another to work with older, unmaintained compilers, with many projects being unable to compile there (the only "edition" is 2018, 4 years now which is starting to look like C++ standard levels of time).
Because like Potter's projects, who the hell ever needed an LTS release? Can't/don't want to update everything every week? Your problem. Now try to choose a single compiler release for your distro.
IMHO, either you have too many big features on each release, and therefore the "editions" should track that, or those are not that big of a deal, so no edition bump is needed and we can focus on binary compatibility, maybe? maybe have sub-editions, like 2018.3?
So yeah, I love rust, and this is really the only bad thing I have to say about the project. Honestly, if there was an LTS release, maybe just one for rust "edition", maybe use editions better, I think everyone would be super happy and most problems would be resolved.
Rust isn't against shared libraries per se, but it doesn't have a stable ABI. ABI for a language with generics is a very tricky problem, and there's no solution on the horizon yet.
As for LTS, there is indeed a stand-off with Linux distros. Rust bets on Chrome's update model, where updates are small and backwards-compatible, so everyone is on the latest, and versions don't matter. Linux distros want Rust to have Internet Explorer update model where there are only updates every X months or years, and developers have to specifically test and work around to support multiple old versions.
Note that Editions aren't language versions. They're like "use strict" in JS. They only toggle warnings and small parsing details, but there's only one Rust version. Every Rust edition can use any Rust feature, as long as it parses. For example, everything new added in 2020 is available in the Rust 2015 edition.
> Rust isn't against shared libraries per se, but it doesn't have a stable ABI.
I'd like to point out that this effectively means "it's not against shared libs, but it will actively ignore anything needed to work with them"
The "move fast and break things" is fine, as long as you are the last link in the chain. Rust is the first.
> ...there's only one Rust version. Every Rust edition can use any Rust feature, as long as it parses. For example, everything new added in 2020 is available in the Rust 2015 edition.
IMHO this is a great feature...for the last link in the chain, not the first.
Note how this is only possible since for now there is only one rust compiler. As soon as GCC or others get ready, how do we sync between features supported? IMHO eventually the "editions" will be treated as minimum version to compile with.
Also, as more and more software is written in rust, lack of lts will force the users to update whole systems every 2 months (and making dynamic linking impossible will only worsen things). I still get 30Mb/s flat connections, and even with that multi-GB updates are a pain. Now imagine that for countries that are worse off.
It's not impossible to work with, it just makes a lot of management things a constant (small?) pain that we had eliminated before.
> Well, we can all agree that the solution should not be "we'll just require everyone to change all their code through this library"
I definitely would like better language support. But IMO the solution shouldn't just be "flip a compiler switch and all your normal data structures have a stable ABI" either.
What I would really like to see is a cross-language ABI (that's more fully featured than then C ABI), that can be opted into with `repr(polyabi)` or whatever it ends up being called.
> IMHO eventually the "editions" will be treated as minimum version to compile with.
This doesn't work, because new features are not only added to newer editions, but to as many editions as possible. The vast majority of new features, when they land, are added to every edition.
> Rust isn't against shared libraries per se, but it doesn't have a stable ABI.
The Rust stable ABI is simply the C ABI. This doesn't work so well with features like generics as you mention, but it's good enough for interfacing with separately-built shared libraries.
Yes this is a piece of opinion, not a scientific measure of anything. This is just a report of the voices of the people I'm converting to Rust because they are never heard.
The compound effect of small additions every 6 weeks is complexity.
Yes there are editions. But from a newcomer's point of view they only add complexity.
Feel free to disagree, but I'm convinced that short release cycle and feature bloat are related. I simply don't want Rust to become the new C++ (which is the feeling of a lot of people).
As I said over in /r/rust, I think this claim of yours is still interesting because it’s a matter of perceptions. I’m certain that this perception is erroneous, but impressions still matter. If you want to succeed, it helps to manage public relations proactively.
Thank you for the heads-up! I missed Reddit's thread as I usually visit social networks only the weekends.
I've bookmarked the page and will for sure read all the comments this weekend, they look very interesting (especially yours, that I've flew over)!
That being said, I stand by my point: Short release cycles are an illustration of The Compound Effect.
> A programming language is a platform. You can't build a thriving ecosystem on top of an unstable platform. We need, as a community, to find a solution to bring calm and focus to Rust, and then we will be able to stabilize and build a great ecosystem of libraries on top of that platform.
> Short release cycles are suitable for products, as you can remove features or UI elements, and thus complexity can decrease over time. But for platforms, it means that you can only add things, as removing parts of a platform will break backward compatibility. Thus complexity may only increase over time.
I would love to see almost "empty releases" in order not to add non-essential features and thus avoid feature bloat.
But then, what is the point of short release cycles if it's not to add features? Wouldn't longer releases cycles make more sense?
Most Rust releases are almost empty. The ones that add something like async are exceedingly rare. Maybe once in a few years?
And what would be the point of sitting on small, well tested, changes for six months or a year? What if it's two or three years before the next major feature is ready for stable? Do we have to hold back all the small improvements too?
For example, making a function const allows it to be used in more places. This can be a big benefit for users. It doesn't help anyone to delay that once it has been decided it is const.
This will be an unpopular observation in certain circles, but to any outsider Rust is already visibly as complicated as C++. Rust, like C++, will only ever become more complex, never simpler (except in a certain sense I return to below).
This is no indictment. Rather, it is a necessity, and a prerequisite to industrial success. The world is complex, and will not adapt itself to a language. A language must adapt itself to the problems the world needs solved. Failing to address a need sends users to languages that do not.
The best that can be done is to start as simple as possible, and then develop as required. (C++ did did not get the luxury of starting simple, but only as simple as was, then and there, possible.) Every language that succeeds becomes, eventually, as complex as its users can handle. The limit is human-scale. The pressure to grow has no natural limit.
There is a real sense in which added complication is needed to give an experience of better simplicity. We see this frequently in releases: restriction X has been removed. The surface texture of the language has become smoother, at the expense of the implemention, which needs to grow to implement the relaxed restriction.
It is always easy to justify removing restrictions, simplifying the description of the language. But this is how languages grow. As restrictions are removed, code in the language becomes simpler. The language takes on more responsibility, so the programmer has less. This is a positive development.
Rust is already a language that caters mainly to professionals, that demands serious education to adopt successfully. The majority of programmers will never succeed in adopting Rust. That was an early choice.
Every language is determined by its choices, which box in unpredictable later choices. Sometimes the right early choice forces what seems like a wrong later choice. That is our lot as humans in an unfolding world.
Celebrate Rust's trajectory as exactly what is needed to mature and succeed in a difficult world.
From the outside (not actually writing Rust code yet) it looks like Rust saw C++ metastasize from an overcomplex big language into an even more overcomplex huge language, and then said HOLD MY BEER!
Encouraging people to go async / event based looks like a huge mistake to me. Code becomes much harder to reason about and you get a ton of additional complexity to worry about.
A much better way is to provide a layer that looks synchronous on top of asynchronous mechanisms. Like going for declarative programming, or make it look like "one thread per request" and have implicit timeout handling via exception you can catch or so.
I think the compartment threading model is one of the main reasons why COM is so successful.
This is a common outsider view, but it's based on wrong assumptions. You think Rust 1.0 was released as a complete language, and now they're just adding useless bells and whistles.
While in fact Rust 1.0 was a bare-bones MVP, missing basic functionality, with an annoyingly inflexible implementation of the borrow checker. You couldn't print or copy an array larger than 32 elements! People still complain that the standard library can't generate random numbers and you need a 3rd party library to cast an integer to an enum (really!)
Since 1.0, Rust has been mostly filling in holes, and removing gotchas. Apart from async, a lot of changes can be summed up as "this obvious code didn't compile before for weird technical reasons, but now it just compiles".
Async started in 2015 with mio library, which was a thin wrapper over Linux epoll. People have recognized that it's tedious to use it, and proposed Futures in 2016, which made it easier. Multiple limitations of Future's APIs were became apparent, so in 2017-2019 there was a lot of work to remove known problems and annoyances. That's the async API: 4 years of real-world experience and simplification of async code. As someone who's used it during that time I can assure you that `async fn` today is easier and clearer than everything Rust had before it.
I can relate to that. It would be great if new language features that make it into the stable version would require a contribution to Rust's documentation in a way that is easily discoverable by interested developers. Which brings me to a more general issue. Blogs from eager developers, who want to land a job in Silicon Valley, which don't contain any direct nor indirect information which could help readers quickly determine if an article is outdated or not.
How difficult can it be to add a date to an article or the version of the Language/framework in question? It always makes my blood boil when I have to find out by myself that a certain blog article, while it may be written well, isn't relevant any more.
In regards of Rust's own documentation some form of diff system eould be great. Last time I looked intonusing Rust was more than a year ago. I would love if I could enter a date or version, and get displayed all changes to the documentation and language between then and now. It would also be helpful when developers have to take over maintenance of code from a former colleague who isn't available any more.
Is there a company behind Rust? Do developers who contribute to the project receive at least market rate salary?
I can't help but think that this kind of model where a group of volunteers creates something of huge value for big corporations for free and then corporation takes it and use in their multi-billion projects and mostly pay in exposure, is a con to weasel out of paying salaries, royalties, taxes by those big corporations.
They promote open source so that they don't have to allocate budgets for R&D, because there is always going to be a group to fall for open source PR and will do the heavy lifting for free.
Then once the project matures enough, some execs will feel guilty that they use something they didn't pay for and built another beach house and got another jet and they will announce they'll commit some of their company resources to "help", but in reality this is just another PR piece.
A lot of people fall for that because they think if they have a great "open source" project in their resume, then somehow one of the big companies will hire them and maybe this will change their modest lives and they'll finally taste middle class living. But that rarely happens.
I think developers should unionise and start demand that those big companies will pay royalties for using "open source" code.
Its development was originally sponsored by Mozilla. But they recently laid off most the Rust team. However, Facebook, Microsoft and Amazon now all have Rust teams employing core developers.
I think all contributors should be paid once a big company starts using the project. The current state of play in my view is unethical. Developers do the hard work in hope they will be hired some day in the future and that not always happens and they won't be reimbursed for their time spent prior to being hired.
In many cases these projects are also developed by privileged developers who can afford to work without pay because they have wealthy parents and so on. This indirectly creates a disadvantage for people from poor backgrounds as in the open source world you are expected to work for free and people who cannot afford to do that are excluded.
Rust has had almost six thousand unique contributors, with about 300 to 350 contributing to any given release these days. And that only counts commits landed in rust-lang/rust, none of our other repos, or non-commit contrutbions. Rust is larger than a lot of companies, at this point.
That being said, you’re not wrong that people deserve to be paid for their work, and the foundation was created in part to help work on this topic, to help the project pay bills and encourage employment, but I’m not aware of many, if any, open source projects as large as ours where everyone or even the majority is paid.
Companies that use this software have billions at their disposal (often through creative accounting), and there is no excuse to not pay. Perhaps this could be based on % of the company revenue and then split similarly how artists are being paid their royalties.
I think there is an opportunity for some big companies to redeem themselves and create such system and amend licenses so that it is ensured all developers are paid if company that is using the projects has revenue above certain threshold. Ideally this could be included in Github and other platforms on a opt-in basis (for developers), but in the future it should be enshrined in law.
I'll vote for any party that will look into exploitation of developers.
> I think all contributors should be paid once a big company starts using the project.
Wait, why would we want to deter big companies from using and supporting Rust? That makes no sense to me. This pervasive big-company-envy is something that I just can't grok here at HN.
For me it is not only about Rust but any open-source software. Companies essentially get labour for free and they don't have to commit their own resources to take on employees and they don't pay salaries and tax. This creates advantage for privileged developers who can work for free and "show off" and there are less jobs for developers from poorer backgrounds as there is nothing like Rust to develop, because companies can just snatch an open source project.
Do you not think this is weird that these companies have billions and billions of cash lying around and developers who helped them make that money probably still live in a rental shoebox?
I think this was a great article, but the focus on the release cycle was probably not hitting the target as that is not on the primary feedback loop for rust development.
That said, it is natural that any successful product goes through the explore, expand, exploit phases (see Kent Beck). And this is perhaps a sign that Rust is approaching the exploit phase, where changes should be slower and focus shifted to reducing overhead.
Perhaps a future Rust edition (next after 2018), will have a list of features removed as it's main selling point?
Still I agree with (out) boats. Rust should complete it's main concepts first. Then we can tidy our room. Promise?
242 comments
[ 6.6 ms ] story [ 274 ms ] threadThere hasn't been a big feature since async/await, and the noise around that is now in library user space - as was to be expected.
There is a rust 2021 edition coming up, but that is also looking to be very modest with very few breaking changes. Like adding `TryFrom` to the standard prelude, and deprecating missing `dyn` keyword for trait objects.
It's the classic elevator issue in reverse. If you want to make an elevator faster, put up mirrors so people look at themselves instead of their watch.
Rust appears to change fast, because the changelogs are so detailed, but actually it's stable. Maybe we need to hide the detailed changelog and replace the main one with "minor bugfixes and constness updates".
The transparency is hugely appreciated by many. It's just that the approving voices are usually silent while the disapproving ones are always loud. Don't let that mislead you. You are doing great.
While perhaps not a large change in practice, this seems like the sort of thing that incurs a large cost when it comes to updating your mental model of how the compiler works, what it can and cannot do, and what options you have when it comes to implementing something.
It's like how you can get some weird set of complex rules and after a bit of time and practice you can just apply them without thinking much about it. However if you suddenly change those rules - even to make them simpler - you'll have to spend awhile readjusting.
It doesn't make the changes bad, but it might explain why people trying to keep up with Rust feel it's changing more significantly than it actually is.
1. Write some code that does something tricky with borrowed types
2. It won't compile. Search online for the error message. Find the Rust github issue about adding support for doing things that way.
3. Try to find or think up a different way to write the code. Go to 1.
GP is referring to changes that make compilation succeed at step 1. These changes will save newbs from many hours of frustration. The cost of these changes is minimal. Actually they free up a lot of mental capacity currently used for workarounds.
I'm really happy with Rust and the steady progress made by the core team. Rust stable is really excellent to work with.
Trying to keep track of what workarounds you do and do not need to use is hard. Removing workarounds is good, but still an expensive step. Applying a large set of rules can be quite easy after an adaptation period, but changing those rules remains hard. Even if the new rules are simpler.
I'm not saying Rust shouldn't be making these changes. I'm just saying I think this might be part of the reason why you hear comments about how hard it is to keep up with Rust.
Why?
If you simply do NOT update your model won't that work just fine? You would continue to avoid certain constructs that used to bother the borrow checker; your code would work fine, and the compiler wouldn't complain exactly as it used to.
I'd guess most people using Rust and checking the changelogs are people who are interested in keeping up with Rust. They are likely to update their mental model because they wish to.
And as a result, they often have to deal with these 'expensive' updates which makes it feel like it is difficult to keep up with Rust.
Contrast this to e.g. Go, which has a ~6 month update cycle, and most of the updates are boring. The main thing relevant to me personally for Go's recent 1.16 update is embedding files, and that's more of a "I can use it when I get to it" thing. Rarely does a Go update require action on my part, and since I started using it full time January last year, I've NEVER had to change any existing code. Neither required, nor because the language has solved something more clever.
Granted, that could be considered a bad thing, and I wouldn't mind some additional features to reduce the amount of code I have to write and maintain, but still.
You will get broken code if you rely on nightly features or if you change edition. My nightly code breaks about once every few weeks but everytime one or two features begin moving into stable and it gets closer to being on pure stable rust, not requiring any unstable things anymore.
So really, if you're writing rust to against stable rustc, you don't need to pay attention to much.
Rust's stability guarantees mean that you don't need to take any action at all.
Breaking changes (unless soundness is involved) only happen with editions and even when a new edition comes out and you update the compiler, you still don't need to do anything unless you explicitly change the configuration of the project to the new edition.
The only thing you might want to do, if you use clippy (a linter that comes with the rust toolchain). Is to check whether it complains about your code due to new check. If that's the case, you get told what to change and why.
1. Rust has very strong stability guarantees. If you want to you can continue coding like it's Rust 1.0 even on the latest compiler.
2. The rate of releases is independent of the rate features are added. Nightly is a playground for feature additions and whatever else. Many may not ever make it into stable, and many might hang around for many years before they are read to be stabilized. A consistent release schedule of every six weeks, whether there's much new or not, means there's no harm in delaying something for a release or three. This vastly reduces the pressure compared to a 3 year release cycle where missing the window means a very long wait.
Rust's releases tend to be very small. Even the big async addition was only the async MVP, not the final product. I think this is probably the source of most complaints because it does introduce some genuine churn for async projects.
But as always this is hard to discuss in the abstract. At least not without some idea of what features people think shouldn't have been stabilized or which they think were rushed.
Btw, here's a good article that attempted to look in to this more objectively:
https://steveklabnik.com/writing/how-often-does-rust-change
I also understand that Rust is quite backwards compatible which is good but a planned better version of releases would be easier for everyone to keep track, update codes, etc.
As long as the compiler remains backwards compatible nobody forces anyone to rewrite programs that deliver their requirements at the time they were developed.
Major compatibility breaks occur on a very long time-frame and most certainly with a version bump prominent enough to draw anyone's attention. Personally, I expect builds to suddenly break on dependencies rather than anything else.
It's a non-issue.
There have been at least two cases where Firefox build broke due to having a too recent version of Rust installed. The stability guarantees may be fairly strong but it's definitely not perfect.
Of course it's good that they fixed the UB.
I understand what you're saying, but anyone who knowingly relies on undefined behavior deserves whatever pain they get, and anyone who didn't know they were relying on undefined behavior, needed to know about it.
Not sure I have the same experience or agree with that. Sure, Rust has a 6 week release cycle, but most of the time the releases are bug fixes or moving library additions into stable. Take this release for example: the only change is ARM support on Linux and a small update to the test framework. I’d hardly describe that as bloat.
https://blog.rust-lang.org/2020/12/31/Rust-1.49.0.html
> As a rust developer, I need to remain up to date with the latest developments in order not to produce code that is obsolete as soon as it’s released
Clippy should help with that, it usually flags deprecated code or better/more up to date ways of doing something. I don’t think you need to keep on top of every RFC, just use what you need.
Apart from that, Perl is not a substitute for Rust or vice versa, regardless of the amount of typing involved.
It... doesn't, though? Rust's syntax is pretty aggressively conventional, from my perspective.
Looking at the punctuation symbol tokens, almost all of this is common to many languages: https://doc.rust-lang.org/reference/tokens.html#punctuation
The symbols that come to mind when I think about my experiences writing Rust are: - <> for generics - ? for early-return errors - Macro invocations require a ! - Match statements use => - ' for lifetimes - #[attrname] for attributes - |x,y| for closures - -> for return types
All the other common symbols I use feel too conventional to seem worth mentioning, like {} for lexical scopes, = for assignment, +-/ for math, foo() for function calls, foo.bar() for method calls, (a,b,c) for tuples, [1,2,3,4] for arrays, <>!== for comparison, "quoted" 'strings', / comments */ and //comments, etc.
I agree that might_fail()? and 'lifetime are different, but everything else I listed seems lightweight, and very common for languages to use symbols for. <> is common for generics from C++, but alternatives I've seen are [] and (), also symbols. Matches use =>, and C's switch cases use :, also a symbol.
Using macro_rules to define macros is pretty symbol-heavy, I guess?
Usually when I see complaints like this, they come down to complaints about the lifetime syntax, and not liking the use of ' for anything besides quoted strings.
If you disagree, could you explain how I've missed or misunderstood your point? Can you show some examples of normal Rust code that uses way more symbols than normal Perl?
As a counter examples, Go release roughly every ~26 weeks and mostly has releases with minor updates. Chromium releases every 6 weeks but not every release has major updates; they are mostly bug fixes and minor improvements. Even Android is decoupling its system services into components which can be updated through the Play store at a much faster cadence than their yearly releases.
I agree that Rust needs to now focus on polish over new features at this point, but I'm not sure that Rust should've done something differently, especially around its release cadence. I don't think it would've been a good contender for serious companies if they hadn't invested heavily in async, for example.
I was under the impression that rust is pretty stable?
Like web browsers get updates on a fast cadence and it rarely breaks existing web pages.
There is not a lot of the former, but there is some of the latter, and even if it's self-imposed, some people do feel that pressure.
However, the ground truth is that the design of significant new language features basically stopped in 2018. The work now is shepherding through the language extensions the project already committed to in the first few years after 1.0. For example, const generics, which will have a stable MVP in the next release, was first begun in 2017. Generic associated types, which are still not near stable, in 2016.
And my own view, these remaining features are a nearly "feature complete" Rust. Future extensions will be either more niche (a lot of attention in the last few years has been aimed at features to make writing unsafe code less error prone, which wouldn't visibly impact users who write only safe code) or less substantial (such as a syntactic sugar that would improve a lot of users lives, but not deeply change how they write code). And that's actually very good.
Regular releases of the compiler are awesome for the same reason continuous deployment of web apps is - each release only packs a small number of features. The chances of something breaking are much smaller than if it was a massive release of hundreds of features, all of which need to be tested in isolation and then with each other. The releases page (https://github.com/rust-lang/rust/blob/master/RELEASES.md) shows how rare it is for a fix release to be made. Even when it is, it's something minor.
Making the language easier to learn is a high priority. Many people are working on this actively right now - better documentation, better error messages, better IDE experience and so on. OP has misdiagnosed the root cause and blamed something that actually makes it easier to learn the language.
This psychological tinkering isn't helpful. People can push unfinished stuff in any situation. E.g. you can close it off 5 months in and then stabilise for a month.
I don't think the OP is having trouble learning. They're having trouble with the almost-monthly changes.
I'm curious, what in there would make someone have to deal with the changes?
But they don't in Rust. My example of Min Const Generics is an example of this. Async-Await (developed by GP on this thread) was also delayed to give it more time to bake.
I urge you to look at the releases page (https://github.com/rust-lang/rust/blob/master/RELEASES.md). Look at how few user facing changes are made with every release. This is a good thing! As long as you're ok with skipping these and the performance improvements, you can stay on an older release for basically forever. Most Rust libraries are conservative about their minimum supported Rust version (MSRV) so there isn't usually a push to upgrade at all.
If the OP wants a compiler and toolchain that only changes every six months, that's already available. He can stick with the same compiler for six months or even longer with 0 downsides.
if you work on safety/security critical systems upgrading the toolchain is considered like changing the tires on a moving vehicle. We have introduced and many weeks later discovered critical (and hard to trace) bugs simply by changing -O2 to -O3 in gcc that ended in sporadic crashes when cross-compiling for 1 specific platform. (which is a change much less severe than upgrading gcc itself) And I'd be surprised if upgrading the toolchain wouldn't potentially introduce similar hard to trace issues in rust.
My point is that just because the first 2 months after upgrade look like there were no required changes in code doesn't mean there are none. I see rust being used in very large companies for internal projects, test harnesses, and other glue/plumbing. And the places I know are really reluctant to go all the way in and substitute their ~30 years of experience with C/C++ with something that remains a constantly moving target. To be fair there are other reasons such as culture, and distribution of skills across the team that drive these decisions but my main point still holds (i think).
I mean, even with C, there is a very circumscribed subset that you use for "safety critical" applications.
2) People are banging on about Rust not being stable but the Rust Embedded guys DO lag for stability--so you can have stability if you choose. And Rust is by far the best language I have seen about being able to stay on old compiler versions and still use newer libraries.
3) I find crappy libraries to be the biggest threat to Rust's sustainability. There was a big "Gold Rush" mentality and a whole lot of unqualified people built a whole lot of crap libraries with no good way for someone to come along later and to flag "That's a crap library, please remove it from crates.io permanently".
Sure, this happens regularly in C and C++ because large programs inevitably depend on undefined behaviour, and changing compiler versions, optimization levels and target platforms is allowed to change that behaviour.
For the last five years I've been writing 99% safe Rust code, which is designed to have no undefined behavior, and I think it's not a coincidence that I can't remember ever having a compiler update break code at runtime. Once in a long while a compiler update will fail to compile some existing code, but that's not a safety issue.
The idea that C and C++ compilers are somehow more stable across releases is a mirage. https://lwn.net/Articles/845691/ https://lwn.net/Articles/845775/
This sounds more like undefined behavior in your codebase than a compiler error. I don't know Rust but I'm pretty sure the whole selling point is that you won't run into problems like this.
As an aside, the clang bug would also affect Rust if they used that type of optimization (assuming strict aliasing rules).
[0] https://lists.isocpp.org/std-discussion/2020/10/0882.php
No, this bug cannot affect rust, because rust wouldn't allow to pass into a function three mutable references pointing to the same object. It wouldn't even allow two, nor one mutable and one immutable. Either it pass one mutable reference, or any number of immutable.
It doesn’t happen often, but it does happen.
Anyway, Rust has found plenty of noalias bugs in clang, which is why it still doesn't compile with noalias optimizations turned on.
It absolutely happens, but less often than you would think.
Rust has a tool named "crater" which compiles and executing tests for every package uploaded to crates.io (and some which are just on github).
It's not perfect but supposedly it catches quite a lot of bugs.
The most used enterprise OS, Windows, is rapid release too -- every 6 months, coincidentally! But there's a LTSB branch you can use. Java releases every 6 months too, and that hasn't halted enterprise adoption. Similarly with C#, not every team jumps to the latest language level just because it was released. Teams should pick language updates at a speed that suits them -- but hopefully not so slowly that moving to newer releases becomes difficult.
Similarly with Go. Why should it be any different with Rust? To the extent that enterprises are using the latter two in massive numbers. The key thing is, as others have noted, is stability and a lack of breaking changes.
Exactly when it comes to Java, even though there is now a 6 month release cadence, take a survey of which version most are using. Certainly every time I bring this up, someone pops up and says, "I'm using 11" or "10". But the vast majority of "enterprises" are at max, Java 8. And they'll remain on 8 until something forces them off of it. Enterprises by nature move at a glacial pace. So their reason for adopting Java is not because it's "moving fast".
I was replying to the parent poster, who said that moving fast is a roadblock to enterprise adoption. Whether enterprises adopt Java because it's moving fast is another question altogether. Certainly no one is deserting Java because of the decision to boost its release cadence.
> Enterprises by nature move at a glacial pace
I think it depends on the enterprise.[1]
Cyber-Security has changed the game for many enterprises very fundamentally. Well-run enterprises now patch more promptly than many consumers -- at least, certainly the consumers who don't auto-update. Well, unless they want a Maersk-like incident[2], or be infected by ransomware. Maersk's incident cost it $200M if you believe Forbes.
About slow JVM upgrades, a lot of that is a cost/benefit calculation or poor technical leadership. CIOs and COOs (or audit, for that matter) have no interest in which Java version you use. The only questions are: Is it secure? Does it make commercial sense?
For actively developed software, staying on a recent-ish Java isn't a problem (many good enterprises have adopted Devops in some shape and form -- just add a task to your CI server to test on the latest JRE) once your engineering team has crossed the Java 8-to-11 hump. If you do that, you get to not pay Oracle $$$ per desktop/server every year (or you could use Corretto etc, but most enterprises will choose to pay Oracle). Or you could simply upgrade for the productivity & JVM improvements.
Legacy products not in active development are another matter, but even there -- the cost of not getting security updates is too high nowadays, so you have to spend money to secure it -- and legacy software has other costs too[3]. So unless you're a developer working on a legacy app, or an app who's design is so poor that it's locked into Java 8, there's no reason you couldn't be on Java 11 soon and get on the rapid cadence train yourself thereafter. It's really about how nimble your team is.
Of course, you could be unfortunate enough to work in an enterprise that doesn't take cyber-security seriously, in which case YOLO.
[1] https://news.ycombinator.com/item?id=25873325
[2] https://www.forbes.com/sites/leemathews/2017/08/16/notpetya-...
[3] https://arstechnica.com/tech-policy/2021/02/citibank-just-go...
Sure, but there's also things like how long will the current version be supported if there are security issues, or similar. People also want a version that will be supported with bug/security fixes for 6 or 12 months vs "Oh it's broken? Upgrade to head."
> This psychological tinkering isn't helpful.
The former comment is thoughtfulness about the ways that a system of work influences contributors mindset and thereby project quality. Even if the specific conclusion was incorrect, the earnest attempt is necessary to project health. If you disagree, you probably want to short-sell Toyota stock.
> you can close it off 5 months in and then stabilise for a month.
This doesn't help. If a release happens every six months then regardless of what you do during the release cycle, you are faced with situations where someone has a work item just about ready to ship in release X, but not quite, and you face enormous pressure to ship it in release X rather than in release X+1 six months later. On the flip side if you do force it to slip to release X+1 then that's several months of users not having the benefit even though it's ready.
If you're releasing every six weeks, there isn't any such pressure. Less work is shipped prematurely, less work is shipped later than necessary, and developers are less stressed.
And it has been a game changer if you ask me, Jira tickets don't pile up in the test lane, testers don't have to do one big regression tests at the end of the sprint just to sure. Sometimes even making them work overtime just to be sure. The code area that introduced new bugs is way smaller and the bugs have become easier to trace down.
Only if Rust has an awful leadership team organizing those releases. Strong leadership and careful release planning nips this right in the bud. "Your feature was only 'finished' a week ago? No way in hell is it making the release. See you in six months."
The other view is that shipping less frequently encourages features to be shipped fully baked and matured, with plenty of time for careful thought and attention given to their design and implementation.
> shipping less frequently encourages features to be shipped fully baked and matured,
Right, but this is just a view. A significant part of the industry believes that shipping less frequently discourages this. We've found that shipping more frequently allows us to take our time and fully bake and mature features in Rust.
Developing a compiler for a complex language is very different from developing a webapp.
Perhaps I'm being too conservative but I'd have more trust in the language if things were moving slower especially that rust positions itself as a systems programming language fit for production (today). Which is odd because what I want from something that ticks these 2 boxes is interface stability. I have more confidence in Zig or Nim for this reason. Give it another 5 years and it will be a similar mess as C++, or worse: Python (which ended up rolling out v3 which wasn't backward compatible with v2). Also the "safety/security" argument which is their big selling-point which goes out the window as soon as you pull 3rd party crates (as is the case in most of the projects).
> Also the "safety/security" argument which is their big selling-point which goes out the window as soon as you pull 3rd party crates
Not at all. Rust's safety guarantees work in practice. In years working on our largish Rust project we practically never have had to deal with memory corruption or data races.
They don't just work in practice. I spent 3 months last semester being taught in the separation logic "Iris", which is used to formally prove the safety guarantees of Rust as part of the RustBelt[0] project. That was under Lars Birkedal, for anyone curious.
Rust is a language I love doing actual work in, but it's also one I really like from the perspective of the theoretical backing.
That's, uh, a rather bold assertion. Perhaps you could elaborate on why you feel it's "broken by design"? I've never heard anyone take that position at all, much less make an implied claim that it's a widely-accepted position.
Do you realize that at this point Rust is way more stable than those two languages? It's not a critique at all as they are much younger, but these are really bad examples to compare with.
Can you specify, what are these flawed principles? And what would be a better system? Thanks!
This is just a report of the voices of the people I'm converting to Rust because they are never heard.
The compound effect of small and fast changes is complexity.
Uncontrolled complexity is the thing we want to avoid as it's fatal to any project.
Yes there are editions. But from a newcomer's point of view they only add complexity.
I'm convinced that short release cycle and feature 'bloat' are related. I simply don't want Rust to become the new C++ (which is the feeling of a lot of people).
This shows that the rapid pace of change already started to slow.
[0]: https://this-week-in-rust.org/
Software development / computer programming is complex. Hiding complexity is bad. News at 11. /s
So, that said newcomers are free to pick their poison regarding tech stack, language, etc. They can use something simple, easy, friendly, and sort of self-contained. Let's say Ruby on Rails, Django, or C# stuff. Inevitably they'll very soon run into the problem of managing dependencies, platforms, native code, security considerations, performance issues, etc.
Everything is a trade-off after all.
I'm confused... C++ doesn't have a short release cycle and it became feature bloated, so how did that lead you to conclude that the short release cycle of Rust is causing Rust to become feature bloated like C++?
Most of the problems with C++ come from the long release cycle and cause the bloat you're talking about. C++ rushes out unfinished features (see std::visit for a great example) to make a release window resulting in unfinished half working features that are horrible to use full of footguns.
Did you mean to link somewhere more specific?
https://medium.com/pm101/spotify-squad-framework-part-i-8f74...
It is kind of annoying when big libraries that are generally touted as the way to do X require nightly, but again that's my experience as of years ago. Nightly should be understood as a place where churn happens. For me, stable releases have never been anything but what it says on the tin.
Rust is now doing the same. Few in the embedded space find it appealing, many of those who use C++ do (as it is certainly a cleaned-up C++, and a nice improvement in comparison), but too often not appealing enough to switch now, and some in the application space who don't know or don't remember the C++ lesson do adopt it now (sometimes out of sheer novelty) but will likely abandon it later for similar reasons C++ was largely abandoned in that space. So it is really competing for a pretty small and conservative niche -- albeit an important one -- and one with a strong incumbent. If it does very well, in 20 years we might find that 60% of the C++ space has switched over to Rust, and that's about it.
What Rust needs is focus, but it won't have it because I think some of its designers still believe in what C++ believed. That you can have a language that is both high-level and low-level, with the benefits of both and the downsides of neither.So it's being pulled in multiple directions, all while showing poor performance in the market (C++, at least, wasn't just hyped but actually popular). It's not even going after C++'s market seriously, but after the nonexistent market C++ thought it could occupy; the only market it seems to be actually competing over and doing well in is HN-front-page real-estate, the space formerly occupied by Ruby and Haskell. When I was at University in the late '90s, everyone was talking about Haskell will be the language of the future. With almost constant levels of hype, more than twenty years later, it still is. It turns out that for various reasons, when it comes to programming languages, hype and market performance can be completely out of sync for decades. Rust's designers need to choose between adoration and actual popularity. The latter will require some tough decisions. If it's going after the C++ market, it should make itself extremely appealing, irresistibly so, to C++ programmers.
I definitely don't get the feeling that C++ was that popular, I distintcly remember many Linus rants about it. It's just that after years of usage it carved its own niche.
However one pain point Rust does address is parallelism. If you want to use modern systems, and you're going with C++. Good luck. You're gonna need it.
As for the popularity, I think that's moot. But I do agree Rust can't be everything to everyone. One problem it will have for the forseable future, is the slow compile speed. But on the flip side, Rust has been super popular.
But it does one thing no other language does. Safe concurrency without GC. It's like a seatbelt in a car. Once you get used to it, you'll be paranoid its not there.
----
Where I do agree with article author was rate of change. IMO Pin should have never been added to standard library as it currently is. But async was rushed, for god knows what reasons.
if you're doing modern stuff you just use a task-based parallelism lib and pass things by value with libs such as https://github.com/taskflow/taskflow, https://github.com/cameron314/concurrentqueue ...
I'm not sure who is it for, but if it's responsible for Pin and it's related unsoundness issues, that just makes me dislike it even more.
A language with BDFL could have, took a more principled stance and said no async until we prove Pin is safe.
> took a more principled stance
This is very insulting. Bugs are often found in every kind of software. Virtually no languages that exist, let alone popular ones, require proofs before landing new features.
To me it's not a bug. It's a foundational flaw. If Rust was a house, and a bug was a broken window, unsoundness issue would be water seeping into the foundation.
If standard library is unsound, that means pretty much everything derived from/relying on that functionality is unsound.
Adding unsoundness for the sake of pushing a feature out is just bad. It's cutting corners on essential things.
> they also could have said "ship it"
True. But if I know that BDFL is an asshat, then I avoid that project.
Here's why this matters. This response from you is much better! Because:
> If Rust was a house, and a bug was a broken window, unsoundness issue would be water seeping into the foundation.
Yes. Everyone agrees, in principle, that Rust being sound is an important property. Your criticism isn't actually about principles, it (appears to me, anyway) that it is about the specific methods in which we figure out if something is sound or not. You can argue that nothing should be added without formal proof, and that's a fine position to take, but at least it is a specific, actionable criticism that can be discussed directly.
By this standard, virtually all languages have "unprincipled" designers. This isn't even true of only async! We didn't (and still sort of don't) have a formal model of the borrow checker. So you can't really criticize async specifically in this way, you'd have to criticize the entire language.
The way I see unprincipled is two fold: 1) You're breaking your promise 2) In a similar situation behave differently
1) Pin was a problem from the start. Allowing it into std/core was a mistake. The fact they allowed an almost blatantly unsound feature is unprincipled.
I'm not 100% sure of the timeline, but near or before the release there were examples floating of a possible Pin unsoundness. And defense was, it's an obscure thing, no one would really use that in practice. The moment designer says, no one would use that in practice, is the moment they lost.
2) Yeah, I get async was a feature everyone wanted. By same measure, why not add self-referential struct. People want it. It's probably unsound but you can't tell. Maybe there exist a model that allows self-referntial structs.
Similar situation, different behavior
People do want it, and in fact, it is part of async, and directly related to the soundness issues you’re complaint about. The reason such things aren’t in stable is that, while people do want it, people wanted async more, and did the work. The work has to happen, features don’t just magically come into existence.
It doesn't appear to be unresolvable.
But what if the issue was unresolvable? Rust would either have to rollback a feature or basically say, we're sound, except for that part.
The attention thing said by Bjarne by himself when asked on Reddit.
I guess the dream of a perfect low+high level language will never die.
You seem to imply that it's fundamentally impossible ?
... and... doesn't it still work ? An awful lot of C++ applications are being written today, and that can be done at a pretty high abstraction level thanks to the type-level facilities of C++.
> . Few in the embedded space find it appealing, many of those who use C++ do (as it is certainly a cleaned-up C++, and a nice improvement in comparison), but too often not appealing enough to switch now, and some in the application space who don't know or don't remember the C++ lesson do adopt it now (sometimes out of sheer novelty) but will likely abandon it later for similar reasons C++ was largely abandoned in that space.
are we talking about the same embedded? most C shop migrate to C++. most car brands, and a lot of appliances, use Qt for their UI (C++)
C++ is nowhere near as dominant in the application space as it was in the early nineties. "An awful lot" in nominal terms for sure.
> are we talking about the same embedded?
Probably not. C++'s niche is "low-level with capable hardware." Some "embedded" software does actually run on very capable hardware.
what do you call "capable" ? C++ is routinely used on atmega328, a 16mhz uc with 2kb of ram.
You’re rewriting history here, friend.
Hardly anyone was writing embedded C++ in the 90s. Even nowadays I bump elbows with Developers that refuse to make the move from C in embedded.
If we’re talking Desktop apps, well... yeah, Windows was the new hotness, OOP was hot ‘n fresh, and Visual C++ was a BFD. Once more languages came about, people found ones they preferred over C++ (Java was a BFD).
As to your last comment, I’m guessing you haven’t worked in the embedded space with C++ if that is your conclusion
I wasn't talking about embedded in that section, but about applications, and not just desktop.
> Once more languages came about, people found ones they preferred over C++
High-level languages were used a lot before, like VB and other RAD languages. But the belief was that they'd be too slow for many applications, like servers.
> As to your last comment, I’m guessing you haven’t worked in the embedded space with C++ if that is your conclusion
That is correct, and yet the lower the hardware capabilities and the higher the required safety, you see more C and less C++.
Whereas Rust, to me at least, is 'ML-ish with curly braces'. So, a language firmly based in the ML heritage with C-like syntax. So, fundamentally working with types and 'typeclasses' and heavily leaning towards filter/map/fold/reduce/lift/unlift type of thinking. Sure, throwing funtions around as first class objects are not as easy or straightforward as it is in 'real FP' languages, but that's a trade-off I'm willing to take for the guarantees that Rust provides.
I'm genuinely curious what's the reasoning behind being able to assert that 'Rust is a cleaned-up C++'.
- Doing Option<T> -> Option<U>
- At what point do I do Option<T> -> Result<T>
- Should I transpose Vec<Option<T>> to Option<Vec<T>> now or later?
- Often reaching for algebraic data types
- How to map over this to collect it into what I need
- Ah, it needs to implement Hash, Eq, PartialEq ... SomeTrait to make it work the way I want
- Pattern matching all over the place
All of which to me mentally feels more like something along the lines of F#, OCaml or Haskell than C++ that 'normal people write'.
When I did my degree, C++ was taught in the second year and Caml Light in the third.
SML, OCaml, C++ and Haskell are all mentionned.
That's a brilliant metaphor to drive home the safety advantages of Rust! "It's a table saw that won't chop off your fingers!"
That's a "shut up and take my money" proposition. (And it helps that it's a really good table saw too.)
(As another aside, I got to the testimonial from an employer talking about the peace of mind of knowing the workers on the shop floor are safe and it "clicked" for me: you've got metrics and liability for job site safety so you can quantify that peace of mind. We still not there with software quality liability eh?)
"It's simpler than C++!". Yeah, Rust could become a bloated mess and still be simpler than C++. It's like saying that a mountain is not high because it's smaller than the Everest. It's not a good idea to use C++ as reference.
But Rust isn't complex: there aren't many features interacting in a special way with one another with a combinatorial explosion of interactions you need to know in order not to shoot yourself in the foot. (Move semantic difference between Rust and C++ are a good illustration of that).
Actually, in terms of number of different features you'll encounter when onboarding a new project, Rust is far behind JavaScript and PHP (PHP being the biggest example of how feature bloat doesn't kill a language, even if your language is targeted at inexperienced developers).
"Why I rewrote my Rust keyboard firmware in Zig: consistency, mastery, and fun" https://kevinlynagh.com/rust-zig/
In absence of good metrics for the kind of complexity we're trying to discuss I think we kind of have to rely on these sorts of first-person subjective reports from the field.
But it does need to be said, that the approach he was using with Rust was absolutely not the right tool for the job. The author should have been using traits. That's what they're for, and they definitely aren't an obscure language feature.
And that being said, the author mainly complains about features that also exist in C (macros and ifdef, and Rust's version are easier than the C one), would you call C a too complex language because it has macros and ifdef? (I actually think that C is one of the most complex programming language ever written because you need to store too much invariants in your head otherwise it's UB, but ifdef and macros aren't at stake )
- - - -
> I actually think that C is one of the most complex programming language ever written because you need to store too much invariants in your head otherwise it's UB, but ifdef and macros aren't at stake
Like I said, without metrics we're just trading subjective anecdotes.
Metrics for complexity of machines is a subject I find fascinating, ever since I read Ashby's "Introduction to Cybernetics" wherein he asks the question "How can we measure the complexity of a machine?" in the context of a formal system for describing machines (Cybernetics.)
There is also the concept of "Kolmogorov complexity" https://en.wikipedia.org/wiki/Kolmogorov_complexity
We could compare the sizes of compilers for C and Rust.
We could teach each to different randomized groups of students and see how quickly people learn to write (safe!) code in each.
Yes, this one guy made a wrong turn once. If you want to conclude from one user making a mistake that a language is complex then you're just going to conclude that programming is complex … Everyday, with every language under the sun, people make mistakes, great discovery.
I'm not blaming “the user®” here, I'm blaming the blog post writer who makes a mistake and concludes that his tool is responsible for it and that he should tell the world how bad the tool is.
> Like I said, without metrics we're just trading subjective anecdotes.
Well that sentence is pretty ironic given the previous one, nevermind.
> We could compare the sizes of compilers for C and Rust.
I wonder what conclusion you'd draw from such a comparison. That assembly is the least complex language in existence, followed by Brainfuck and Chicken?
> We could teach each to different randomized groups of students and see how quickly people learn to write (safe!) code in each.
Oh I actually like this one. For Rust, you'd need to run a study to find out, but for C the answer is trivial: Never. Nobody on earth know how to write safe C. Not even DJB, not even Theo de Raadt, or Richard Hipp, or Brad Spengler. For almost 50 years, the brightest minds of computer science have tried to write safe C code, and consistently failed. Can we conclude that this language is a little bit too complex for humans, or should we wait a few decades more?
I wish there was a C with a borrow-checker like Rust, but without everything else.
And what decisions would that be? Your post seems self contradictory to me because it implies that Rust is both too "low abstraction" to be "extremely appealing" to C++ crowd, and too complex and "hard to analyze" to displace C in use-cases that require portability and/or are resource constrained.
If there's anything we can learn from programming languages -- be they C, C++, Ruby, PHP, Haskell, or Java -- riding the hype-train led by PL enthusiasts and early-adopters is not a good recipe for long-term success (even if it is a good recipe for long-term hype). Like with fashion (and I think HN is more like GQ or Vogue than actual industry news; i.e. it is more aspirational and inspirational than descriptive or prescriptive), the languages people talk about and those they actually use for many years are usually not the same.
That's exactly what Rust is doing. It used to have a runtime, green threads and a GC, but it doesn't because that's not what C++ developers want. And recent development work has been focussed on const generics and const fn which are both keys things seen as missing by C++ developers.
Why would you want Rust to target lowest-common-denominator developers and become new VB or php? All it needs is enough momentum to become self-sufficient, which seems to be actually happening now with Rust Foundation and news of its usage in some major companies that can set the trends for whole industry (Amazon, Google, etc.).
Rust wants not that I wants. It seems people replacing NodeJS with it.
From the perspective of someone who's been writing Rust professionally for the last few years, the hockey-stick curve started kicking in in late 2020 or so.
But you can even have a rough estimate according to your own measure. There are roughly between 50K and 100K developers working at FAANG (maybe replace Netflix with Microsoft). How many of them would you guess are using Rust?
I don't think Rust and C++ have the same level of abstraction, for example. Rust has ADTs and pattern matching, C++ only has product types and std::variant.
There's a crucial distinction between input and output types in practice. For a given input type T, Rust makes it possible to abstract over `T`, `&T`, `Cow<'a, T>`, `Arc<T>` etc, by using a trait such as `impl AsRef<T>`.
However, Rust doesn't currently have existential types, so its ability to abstract over output types is more limited. You can implement, for example, `fn foo(&self) -> impl AsRef<T> + '_`, but you can't name that type. So if you want to return an enum, you can't write
```
enum MyEnum { MyT(impl AsRef<T>), MyU(impl AsRef<U>), }
```
Instead, you have to concretize the type somehow, either by boxing things up into a trait object (often but not always possible) or by exposing the generic param:
```
enum MyEnum<RefT, RefU> where RefT: AsRef<T>, MyU: Ref<U> { MyT(RefT), MyU(RefU), }
```
This is a real problem, though one that will be solved through existential types.
> Replacing, say, a concrete type with a trait is about as much work in Rust as it is in Assembly.
I'm not sure what you mean here. I'm not aware of any assembly languages which have traits. Replacing a concrete type with a trait tends to be pretty easy in Rust because mistakes are caught at compile time.
> I'm not aware of any assembly languages which have traits. Replacing a concrete type with a trait tends to be pretty easy in Rust because mistakes are caught at compile time.
I'm not thinking in terms of language features but abstractions. The best way to see this is to think how many different implementations to a code unit I can do without making the consumer aware? That number is significantly lower for low-level languages compared to high-level languages because things that can be hidden in high-level languages, like layout, storage and lifetime, must not be in low-level ones, hence "low abstraction." Changing something in one place is more likely to require changes elsewhere. Therefore, low-level programs are more rigid, more jigsaw-like, and their evolution more difficult.
It is true that a compiler that tells you if you missed a change helps a lot, but it doesn't change the nature of the low-level language, even though it improves its ergonomics (although it's not so simple, as sometimes even correct programs are rejected) -- you still need to do all the extra work, but it doesn't take quite as long.
Not really; Rust is very careful to avoid leaky abstractions, compared to C++. It's definitely "low level" in a foundational sense (even reminiscent of C in many ways) but the limited "high-level" features it does have are incredibly solid and highly usable.
Additionally at least on Windows, Microsoft still believes in C++ for doing the kind of desktop applications you are talking about.
All these scenarios aren't properly covered by Rust in its current state, even the Rust/WinRT project is doing baby steps, very far away from what VC++ offers today.
Haskell doesn't promise the type of control I need. Someone i work with rewrote our main control algorithm and proved it was correct (not in Haskell ,I just fear this problem ), but it took over a minute to run, and this PID loop needs to run at 5hz and leave some processor for other tasks. My c++ isn't proven correct but we have 15 years of production with it.
Rust promises to avoid some of the things we don't like about c++ while still worming in the real world. So of course I'm interested.
I knew neither language, but try as I might I just could never get going with Rust. The syntax is obscure, the concepts are complex. There is also no real IDE for Rust.
Meanwhile Go was much quicker to get working code with, and when combined with the excellent Jetbrains GoLand IDE, my initial spaghetti code was soon transformed into a cleaner and maintainable format. The Go community on Slack is also a great resource.
I appreciate Rust is more complex than other languages and much less easier to pick up and learn on the job though. It definitely takes a lot of practice to get to the point where traits/lifetimes/ownership etc feel like brilliant tools rather than needless complexity.
Comparing a language with a fairly significant runtime and garbage collection to a language with basically no runtime and strict (albeit largely automated) compile-time memory management is comparing chalk and cheese. You might as well say "I tried C++ but ended up going with Python because it was quicker to code" -- of course it was!
See here for more details: https://nim-lang.org/blog/2020/10/15/introduction-to-arc-orc...
This is why I reach for Go by default when writing CLI tools. You will get your job done faster, and it will be much easier to understand and maintain. You will be trading off many of the static guarantees that Rust gives, but it's worth it for CLI tools, most of the time.
If you are writing code with strict performance requirements, then consider Rust. Otherwise you'll likely be adding a whole bunch of complexity for not much gain, and your code will require much more cognitive overhead to understand and contribute to.
In c++ there are foot-guns on every turn. Follow the links for some goodies:
https://en.cppreference.com/w/cpp/language/value_category
https://en.cppreference.com/w/cpp/language/reference_initial...
https://en.cppreference.com/w/cpp/language/template_speciali...
https://en.cppreference.com/w/cpp/language/overload_resoluti...
Building cli tools in crystal is fairly easy thank to the standard OptionParser library. `colorize` is almost perfect, too, in case you want to print some ascii colors. And just like ruby, invoking some shell command is simply wrapping the command with backticks. and FileUtils has ton of features.
Too bad Crystal now only works in POSIX.
* long term support
* choice, in particular in building shared libraries.
While a lot can be argued on the first point, the community seems to be actively against anyone who wants to use or build stuff with shared libraries. Shared libs are extremely useful in resource constrained environments like routers, and the debate on who should update things (distro maintainers vs project maintainers) is still very well out there.
But breaking compatibility every compiler release is a huge pain the butt, and will force those who need shared libs for one reason or another to work with older, unmaintained compilers, with many projects being unable to compile there (the only "edition" is 2018, 4 years now which is starting to look like C++ standard levels of time).
Because like Potter's projects, who the hell ever needed an LTS release? Can't/don't want to update everything every week? Your problem. Now try to choose a single compiler release for your distro.
IMHO, either you have too many big features on each release, and therefore the "editions" should track that, or those are not that big of a deal, so no edition bump is needed and we can focus on binary compatibility, maybe? maybe have sub-editions, like 2018.3?
So yeah, I love rust, and this is really the only bad thing I have to say about the project. Honestly, if there was an LTS release, maybe just one for rust "edition", maybe use editions better, I think everyone would be super happy and most problems would be resolved.
As for LTS, there is indeed a stand-off with Linux distros. Rust bets on Chrome's update model, where updates are small and backwards-compatible, so everyone is on the latest, and versions don't matter. Linux distros want Rust to have Internet Explorer update model where there are only updates every X months or years, and developers have to specifically test and work around to support multiple old versions.
Note that Editions aren't language versions. They're like "use strict" in JS. They only toggle warnings and small parsing details, but there's only one Rust version. Every Rust edition can use any Rust feature, as long as it parses. For example, everything new added in 2020 is available in the Rust 2015 edition.
I'd like to point out that this effectively means "it's not against shared libs, but it will actively ignore anything needed to work with them"
The "move fast and break things" is fine, as long as you are the last link in the chain. Rust is the first.
> ...there's only one Rust version. Every Rust edition can use any Rust feature, as long as it parses. For example, everything new added in 2020 is available in the Rust 2015 edition.
IMHO this is a great feature...for the last link in the chain, not the first.
Note how this is only possible since for now there is only one rust compiler. As soon as GCC or others get ready, how do we sync between features supported? IMHO eventually the "editions" will be treated as minimum version to compile with.
Also, as more and more software is written in rust, lack of lts will force the users to update whole systems every 2 months (and making dynamic linking impossible will only worsen things). I still get 30Mb/s flat connections, and even with that multi-GB updates are a pain. Now imagine that for countries that are worse off.
It's not impossible to work with, it just makes a lot of management things a constant (small?) pain that we had eliminated before.
There are libraries that enable this: https://docs.rs/abi_stable/0.9.3/abi_stable/
static vs dynamic is a linker (and LTO) problem, we can't start asking everyone everywhere to change all their code.
Although the library does look nice for some use cases
I definitely would like better language support. But IMO the solution shouldn't just be "flip a compiler switch and all your normal data structures have a stable ABI" either.
What I would really like to see is a cross-language ABI (that's more fully featured than then C ABI), that can be opted into with `repr(polyabi)` or whatever it ends up being called.
This doesn't work, because new features are not only added to newer editions, but to as many editions as possible. The vast majority of new features, when they land, are added to every edition.
The Rust stable ABI is simply the C ABI. This doesn't work so well with features like generics as you mention, but it's good enough for interfacing with separately-built shared libraries.
Yes this is a piece of opinion, not a scientific measure of anything. This is just a report of the voices of the people I'm converting to Rust because they are never heard.
The compound effect of small additions every 6 weeks is complexity.
Yes there are editions. But from a newcomer's point of view they only add complexity.
Feel free to disagree, but I'm convinced that short release cycle and feature bloat are related. I simply don't want Rust to become the new C++ (which is the feeling of a lot of people).
That is something that is missing in the article. I think it is valuable to know about these opinions, so thanks for sharing them.
Both here and /r/rust (https://old.reddit.com/r/rust/comments/m7seki/the_biggest_th...), this has been pretty thoroughly debunked. If you still hold your position after reading all the comments, I’d be interested in a rebuttal.
As I said over in /r/rust, I think this claim of yours is still interesting because it’s a matter of perceptions. I’m certain that this perception is erroneous, but impressions still matter. If you want to succeed, it helps to manage public relations proactively.
I've bookmarked the page and will for sure read all the comments this weekend, they look very interesting (especially yours, that I've flew over)!
That being said, I stand by my point: Short release cycles are an illustration of The Compound Effect.
> A programming language is a platform. You can't build a thriving ecosystem on top of an unstable platform. We need, as a community, to find a solution to bring calm and focus to Rust, and then we will be able to stabilize and build a great ecosystem of libraries on top of that platform.
> Short release cycles are suitable for products, as you can remove features or UI elements, and thus complexity can decrease over time. But for platforms, it means that you can only add things, as removing parts of a platform will break backward compatibility. Thus complexity may only increase over time.
I would love to see almost "empty releases" in order not to add non-essential features and thus avoid feature bloat.
But then, what is the point of short release cycles if it's not to add features? Wouldn't longer releases cycles make more sense?
And what would be the point of sitting on small, well tested, changes for six months or a year? What if it's two or three years before the next major feature is ready for stable? Do we have to hold back all the small improvements too?
For example, making a function const allows it to be used in more places. This can be a big benefit for users. It doesn't help anyone to delay that once it has been decided it is const.
This is no indictment. Rather, it is a necessity, and a prerequisite to industrial success. The world is complex, and will not adapt itself to a language. A language must adapt itself to the problems the world needs solved. Failing to address a need sends users to languages that do not.
The best that can be done is to start as simple as possible, and then develop as required. (C++ did did not get the luxury of starting simple, but only as simple as was, then and there, possible.) Every language that succeeds becomes, eventually, as complex as its users can handle. The limit is human-scale. The pressure to grow has no natural limit.
There is a real sense in which added complication is needed to give an experience of better simplicity. We see this frequently in releases: restriction X has been removed. The surface texture of the language has become smoother, at the expense of the implemention, which needs to grow to implement the relaxed restriction.
It is always easy to justify removing restrictions, simplifying the description of the language. But this is how languages grow. As restrictions are removed, code in the language becomes simpler. The language takes on more responsibility, so the programmer has less. This is a positive development.
Rust is already a language that caters mainly to professionals, that demands serious education to adopt successfully. The majority of programmers will never succeed in adopting Rust. That was an early choice.
Every language is determined by its choices, which box in unpredictable later choices. Sometimes the right early choice forces what seems like a wrong later choice. That is our lot as humans in an unfolding world.
Celebrate Rust's trajectory as exactly what is needed to mature and succeed in a difficult world.
From the outside (not actually writing Rust code yet) it looks like Rust saw C++ metastasize from an overcomplex big language into an even more overcomplex huge language, and then said HOLD MY BEER!
Encouraging people to go async / event based looks like a huge mistake to me. Code becomes much harder to reason about and you get a ton of additional complexity to worry about.
A much better way is to provide a layer that looks synchronous on top of asynchronous mechanisms. Like going for declarative programming, or make it look like "one thread per request" and have implicit timeout handling via exception you can catch or so.
I think the compartment threading model is one of the main reasons why COM is so successful.
While in fact Rust 1.0 was a bare-bones MVP, missing basic functionality, with an annoyingly inflexible implementation of the borrow checker. You couldn't print or copy an array larger than 32 elements! People still complain that the standard library can't generate random numbers and you need a 3rd party library to cast an integer to an enum (really!)
Since 1.0, Rust has been mostly filling in holes, and removing gotchas. Apart from async, a lot of changes can be summed up as "this obvious code didn't compile before for weird technical reasons, but now it just compiles".
Async started in 2015 with mio library, which was a thin wrapper over Linux epoll. People have recognized that it's tedious to use it, and proposed Futures in 2016, which made it easier. Multiple limitations of Future's APIs were became apparent, so in 2017-2019 there was a lot of work to remove known problems and annoyances. That's the async API: 4 years of real-world experience and simplification of async code. As someone who's used it during that time I can assure you that `async fn` today is easier and clearer than everything Rust had before it.
> I’m a fan of the Pareto principle: 80% of consequences come from 20% of the causes.
This reminds me of the claim that most users only use 20% of the features of a given application.
What is often forgotten though, is that different users will often need different 20%.
I can relate to that. It would be great if new language features that make it into the stable version would require a contribution to Rust's documentation in a way that is easily discoverable by interested developers. Which brings me to a more general issue. Blogs from eager developers, who want to land a job in Silicon Valley, which don't contain any direct nor indirect information which could help readers quickly determine if an article is outdated or not.
How difficult can it be to add a date to an article or the version of the Language/framework in question? It always makes my blood boil when I have to find out by myself that a certain blog article, while it may be written well, isn't relevant any more.
In regards of Rust's own documentation some form of diff system eould be great. Last time I looked intonusing Rust was more than a year ago. I would love if I could enter a date or version, and get displayed all changes to the documentation and language between then and now. It would also be helpful when developers have to take over maintenance of code from a former colleague who isn't available any more.
That being said, you’re not wrong that people deserve to be paid for their work, and the foundation was created in part to help work on this topic, to help the project pay bills and encourage employment, but I’m not aware of many, if any, open source projects as large as ours where everyone or even the majority is paid.
Wait, why would we want to deter big companies from using and supporting Rust? That makes no sense to me. This pervasive big-company-envy is something that I just can't grok here at HN.
That said, it is natural that any successful product goes through the explore, expand, exploit phases (see Kent Beck). And this is perhaps a sign that Rust is approaching the exploit phase, where changes should be slower and focus shifted to reducing overhead.
Perhaps a future Rust edition (next after 2018), will have a list of features removed as it's main selling point?
Still I agree with (out) boats. Rust should complete it's main concepts first. Then we can tidy our room. Promise?