1. 54
  1.  

  2. 29

    The 6-week release cycle is a red herring. If Rust didn’t have 6-week cycles, it would have bigger annual releases instead, but that has no influence on the average progress of the language.

    It’s like slicing the same pizza in either 4 or 42 slices, but complaining “oh no, I can’t eat 42 slices of pizza!”

    Rust could have had just 4 releases in its history: 2015 (1.0), 2016 (? for errors), 2018 (new modules) and 2020 (async/await), and you would call them reasonably sized, each with 1 major feature, and a bunch of minor standard library additions.

    Async/await is one major idiom-changing feature since 2015 that actually caused churn (IMHO totally worth it). Apart from that there have been only a couple of syntax changes, and you can apply them automatically with cargo fix or rerast.

    1. 17

      It’s like slicing the same pizza in either 4 or 42 slices, but complaining “oh no, I can’t eat 42 slices of pizza!”

      It’s like getting one slice of pizza every 15 minutes, while you’re trying to focus. I like pizza, but I don’t want to be interrupted with pizza 4 times. Being interrupted 42 times is worse.

      Timing matters. Treadmills aren’t fun as a user.

      1. 13

        Go releases more frequently than Rust, and I don’t see anyone complaining about that. Go had 121 releases, while Rust less than half of that.

        The difference is that Go calls some releases minor, so people don’t count them. Rust could do the same, because most Rust releases are very minor. If it had Go’s versioning scheme it’d be on something like v1.6.

        1. 20

          People aren’t complaining about the frequency of Go releases because Go doesn’t change major aspects of the language, well, ever. The most you have to reckon with is an addition to the standard library. And this is a virtue.

          1. 8

            So, what major aspects of the language changed since Rust 1.0, besides async and perhaps the introduction of the ? operator?

            1. 10

              The stability issues are more with the Rust ecosystem than the Rust language itself. People get pulled into fads and then burned when they pay the refactoring costs to move to the next one. Many of those fad crates are frameworks that impose severe workflow constraints.

              Go is generally far more coherent as an overall ecosystem. This was always the intent. Rust is not so opinionated and structured. This leads to benefits and issues. Lots of weird power plays where people write frameworks to run other people’s code that would just be blatantly unnecessary in Go. It’s unnecessary in Rust, too, but people are in a bit of daze due to the complexity flying around them and it’s sometimes not so clear that they can just rely on the standard library for a lot of things without pulling in a stack of 700 dependencies to write an echo server.

              1. 2

                Maybe in the server/web part of the ecosystem. I am mostly using Rust for NLP/ML/data massaging and the ecosystem has been very stable.

                I have also use Go for several years, but I didn’t notice much difference in the volatility.

                But I can imagine that it is different for networking/services, because the Go standard library has set strong standards there.

              2. 6

                Modules have changed a bit, but it was optional change and only required running cargo fix once.

                Way less disruptive than GOPATH -> go modules migration.

            2. 5

              That is kind of the point. I love both Go and Rust (if anything, I’d say I’d like Rust more than Go if working out borrow checker issues wasn’t such a painstaking, slow process), but with Go I can go and update the compiler knowing code I wrote two years ago will compile and no major libraries will start complaining. With Rust, not so much. Even in the very short time I was using it for a small project, I had to change half of my code to use async (and find a runtime for that, etc.) because a single library I wanted to use was ‘async or the highway’.

              Not a very friendly experience, which is a shame because the language itself rocks.

              1. 9

                In Rust you can upgrade the compiler and nothing will break. Rust team literally compiles all known Rust libraries before making a new release to ensure they don’t break stuff.

                The ecosystem is serious about adherence to semver, and the compiler can seamlessly mix new and old Rust code, so you can be selective of what you upgrade. My projects that were written for Rust 1.0.0 work fine with the latest compiler.

                The async addition was the only change which caused churn in the ecosystem, and Rust isn’t planning anything that big in the future.

                And Go isn’t flawless either. I can’t upgrade deps in my last Go project, because migration to Go Modules is causing me headaches.

                1. 3

                  Ah, yeah, the migration to modules was a shit show. It took me about six months to be able to move a project to modules because a bunch of the dependencies took a while to upgrade.

                  Don’t get me wrong, my post wasn’t a criticism of my Rust. As I said, I really enjoy the language. But any kind of big changes like async and so on introduce big paradigm shifts that make the experience extra hard for newcomers. To be fair to Rust, Python took 3 iterations or so until they figured out a proper interface for async, while rust figured the interface and left the implementation to the reader… Which has created another rift for some libraries.

          2. 4

            I can definitely agree with the author, since I do not write Rust in my day job it is pretty hard for me to keep up with all the minor changes in the language. Also, as already stated in the article, the 6 week release cycle exacerbates the problem.

            I’m not famliar with Rust’s situation, but from my own corporate experience, frequent releases can be awful because features are iterated on continuously. It would be really nice to just learn the final copy of something rather than all the intermediate steps to get there.

            1. 3

              Releasing “final copy” creates design-by-commitee. Features have to get real-world use to prove they’re useful.

              There’s a chicken-egg problem here. Even though Rust has nightlies and betas, features are adopted and used in production only after they’re declared stable. But without using a feature for real, you can’t be sure it’s right.

              Besides, lots of changes in 6-week releases are tiny, like a new command-line flag, or allowing few more functions to be used as initializers of global variables.

              1. 6

                Releasing “final copy” creates design-by-commitee. Features have to get real-world use to prove they’re useful.

                Design-by-committee can be a lot more thoughtful than design-by-novice. I think this is one of the greatest misonceptions of agile.

                Many of the great things we take for granted are done by committee including our internet protocols and core infrastructure. There’s a lot of real good engineering in there. Of course there’s research projects and prototyping which are super useful but it’s a full time job to keep up with developments in research. Most people don’t have to care to learn it until it’s stable and published.

                1. 2

                  Sorry, I shouldn’t have mentioned an emotionally-charged “commitee” name. It was not the point.

                  The point is that language features need iteration to be good, but for a language with strong stability guarantee the first iteration must be the final one.

                  So the way around such impossible iteration is release only obvious core parts, so that libraries can iterate on the rest. And the rest is going to be blessed as official only after it proves useful.

                  Rust has experience here: the first API of Futures turned out to have flaws. Some interfaces caused unfixable inefficiencies. Built-in faillibility turned out to be more annoying than helpful. These things came out to light only after the design was “done” and people used it for real and built large projects around them. If Rust held that back and waited for the full async/await to be feature-complete, it’d be a worse design, and it wouldn’t have been released yet.

                2. 3

                  Releasing “final copy” creates design-by-commitee.

                  I’m not convinced that design-by-crowd is substantively different from design-by-committee.

                  1. 1

                    Releasing “final copy” creates design-by-commitee. Features have to get real-world use to prove they’re useful.

                    There’s a chicken-egg problem here. Even though Rust has nightlies and betas, features are adopted and used in production only after they’re declared stable. But without using a feature for real, you can’t be sure it’s right.

                    I deny the notion that features must be stabilized early so that they get wide spread or “production use.” It may well be the case that some features don’t receive enough testing on nightly/beta and in order to get more users it must hit stable, but limited testing on nightly or beta is not a reason to stabilize a feature. Either A) wait longer until it’s been more thoroughly tested on nightly/beta or B) find a manner to get more testers of features on nightly/beta.

                    I’m not necessarily saying that’s what happened with Rust, per se, but it’s close as I’ve seen the sentiment expressed several times over my time with Rust (since 0.9 days).

                3. 10

                  It’s not a red herring. There might be bigger annual releases if there weren’t 6-week releases, but you’re ignoring the main point: Rust changes frequently enough to make the 6-week release cycle meaningful. The author isn’t suggesting the same frequency of changes less often, but a lower frequency of changes - low enough, perhaps, that releasing every 6 weeks would see a few “releases” go by with no changes at all.

                  No one is trying to make fewer slices out of the pizza. They’re asking for a smaller pizza.

                  1. 7

                    How is adding map_or() as a shorthand for map().unwrap_or() a meaningful language change? That’s the scale of changes for the majority of the 6-week releases. For all but handful of releases the changes are details that you can safely ignore.

                    Rust is very diligent with documenting every tiny detail in release notes, so if you don’t pay attention and just gloss over them only counting the number of headings, you’re likely to get a wrong impression of what is actually happening.

                    1. 3

                      How is adding map_or() as a shorthand for map().unwrap_or() a meaningful language change?

                      I think that’s @ddevault’s point: the pizza just got bigger but it didn’t really get better. It’s a minor thing that doesn’t really matter, but it happens often and it’s something you may need to keep track of when you’re working with other people.

                      1. 9

                        Rust also gets criticised for having too small standard library that needs dependencies for most basic things. And when it finally adds these basic things, that’s bad too…

                        But the thing is — and it’s hard to explain to non-users of the language — that additions of things like map_or() is not burdensome at all. From inside, it’s usually received as “finally! What took you so long!?”.

                        • First, it follows a naming pattern already used elsewhere. It’s something you’d expect to exist already, not really a new thing. It’s more like a bugfix for “wtf? why is this missing?”.

                          Back-filling of outrageously missing features is still a common thing in Rust. 1.0 was an MVP rather than a finished language. For example, Rust waited 32 releases before add big-endian/little-endian swapping.

                        • There’s cargo clippy that will flag too unidiomatic code, so you don’t really need to keep track of it.

                        • It’s OK to totally ignore this. If your code worked without some new stdlib function, it’ll doesn’t have to care. And these changes are minor, so it’s not like you’ll need to read a book on a new method you notice. You’ll know what it does from it’s name, because Rust is still at the stage of adding baby things.

                        1. 7

                          In the Haskell world, there’s a piece of folklore called the Fairbairn Threshold, though we have very clean syntax for composing small combinators:

                          The Fairbairn threshold is the point at which the effort of looking up or keeping track of the definition is outweighed by the effort of rederiving it or inlining it.

                          The term was in much more common use several years ago.

                          Adding every variant on every operation to the Prelude is certainly possible given infinite time, but this of course imposes a sort of indexing overhead mentally.

                          The primary use of the Fairbairn threshold is as a litmus test to avoid giving names to trivial compositions, as there are a potentially explosive number of them. In particular any method whose definition isn’t much longer than its name (e.g. fooBar = foo . bar) falls below the threshold.

                          There are reasonable exceptions for especially common idioms, but it does provide a good rule of thumb.

                          The effect is to encourage simple combinators that can be used in multiple situations, while avoiding naming the explosive number of combinations of those combinators.

                          Given n combinators I can probably combine two of them in something like O(n^2) ways, so without the threshold as a rule of thumb you wind up with a much larger library, but no real greater utility and much higher cognitive overhead to track all the combinations.

                          Further, the existence of some combinations tends to drive you to look for other ever larger combinations rather than learn how to compose combinators or spot the more general usage patterns yourself, so from a POSIWID perspective, the threshold encourages better use of the functional programming style as well.

                      2. 1

                        Agreed. It has substantially reduced my happiness all around:

                        • It’s tiring to deal with people who (sincerely) think adding features improves a language.
                        • It’s disappointing that some people act like having no deprecation policy is something that makes a language “stable”/“reliable”/good for business use.
                        • It’s mind-boggling to me that the potential cost of removing a feature is never factored into the cost of adding it in the first place.

                        Mainstream language design is basically living with a flatmate that is slowly succumbing to his hoarding tendencies and simply doesn’t realize it.

                        What I have done to keep my sanity is to …

                        • freeze the version of Rust I’m targeting to Rust 1.13 (I’m not using ?, but some dependencies need support for it), and
                        • playing with a different approach to language design that makes me happier than just watching the constant mess of more-features-are-better.
                        1. 2

                          Mainstream language design is basically living with a flatmate that is slowly succumbing to his hoarding tendencies and simply doesn’t realize it.

                          I like that analogy, but it omits something crucial: it equates “change” with “additional features/complexity” – but many of the changes to Rust are about removing special cases and reducing complexity.

                          For example, it used to be the case that, when implementing a method on an item, you could refer to the item with Self – but only if the item was a struct, not it it was an enum. Rust 1.37 eliminated that restriction, removing one thing for me to remember.

                          Other changes have made standard library APIs more consistent, again reducing complexity. For example the Option type has long had a map_or method that calls a function on the Some type or, if the Option contains None, uses a default value. However, until Rust 1.41, you had to remember that Results didn’t have a map_or method (even though they have nearly all the other Option methods). Now, Results have that method too, making the standard library more consistent and simpler.

                          I’m not claiming that every change has been a simplification; certainly some have not. (For example, did we really need todo!() as a shorter way to write unimplemented!() when they have exactly the same effect?).

                          But some changes have been simplifications. If Rust is a flatmate that is slowly buying more stuff, it’s also a flatmate that’s throwing things out in an effort to maintain a tidy space. Which effect dominates? As a pretty heavy Rust user, my personal feeling is that the language is getting simpler over time, but I don’t have any hard evidence to back that up.

                          1. 3

                            But some changes have been simplifications.

                            I think what you are describing is a language that keeps filling some gaps and oversights, they are probably not the worst kind of additions, but they are additions.

                            If Rust is a flatmate that is slowly buying more stuff, it’s also a flatmate that’s throwing things out in an effort to maintain a tidy space.

                            What has Rust thrown out? I have trouble coming up with even a single example.

                            As a pretty heavy Rust user, my personal feeling is that the language is getting simpler over time, but I don’t have any hard evidence to back that up.

                            How would you distinguish between the language getting simpler and you becoming more familiar with the language?

                            I think this is the reason why many additions are “small, simple, obvious fixes” to expert users, but for new/occasional users they present a mountain of hundreds of additional things that have to be learned.

                            1. 1

                              How would you distinguish between the language getting simpler and you becoming more familiar with the language?

                              That’s a fair question, and is part of the reason I added the qualification that I can only provide my personal impression – without data, it’s entirely possible that I’m mistaking my own familiarity for language simplification. But I don’t believe that’s the case, for a few reasons.

                              I think this is the reason why many additions are “small, simple, obvious fixes” to expert users, but for new/occasional users they present a mountain of hundreds of additional things that have to be learned.

                              I’d like to focus on the “additional things” part of what you said, because I think it’s key: if a feature is revised so that it’s consistent with several other features, then that’s one fewer thing for a new user to learn, not one more. For example, match used to treat & a bit differently and require as_ref() method calls to get the same effect, which frequently confused people learning Rust. Now, & works the same with match as it does with the rest of the language. Similarly, the 2015 Edition module system required users to format their paths differently in use statements than elsewhere. Again, that confused new users (and annoyed pretty much everyone) and, again, it’s been replaced with a simpler, more consistent, and easier-to-learn system.

                              On the other hand, you might have a point about occasional Rust users – if a user understood the old module system, then switching to the 2018 Edition involves learning something new. For the occasional user, it doesn’t matter that the new system is simpler – it’s still one more thing for them to learn.

                              But for a new user, those simplifications really do make the language simpler to pick up. I firmly believe that the current edition of the Rust Book describes a language that is simpler and more approachable – and that has fewer special cases you have to “just remember” – than the version of the language described in the first edition.

                              1. 1

                                A lot of effort is spent “simplifying” things that “simply” shouldn’t have been added in the first place:

                                • do we really need two different kind of use paths (relative and absolute)?
                                • do we really need both if expressions and pattern matching?
                                • do we really need ? for control flow?
                                • do we really need to have two different ways of “invoking” things, (...) for methods (no support for named parameters) and {...} for structs (support for named parameters)?
                                • do we really need the ability to write foo for foo: foo in struct initializers?

                                Most often the answer is “no”, but we have it anyway because people keep conflating familiarity with simplicity.

                                1. 2

                                  You’re describing redundancy as if it was some fault, but languages without any redundancy are a turing tarpit. Not only we don’t need two kinds of paths, the whole use statement is unnecessary. We don’t even need if. Smalltalk could live without it. We don’t really need anything more than a lambda and a Y combinator or one instruction.

                                  I’ve used Rust v0.5 before it had if let, before there was try!(). It required a full match on every single Option. It was a pure minimal design, and I can tell you it was awful.

                                  So yes, we need these things, because convenience is also important.

                                  1. 2

                                    You’re describing redundancy as if it was some fault, but languages without any redundancy are a turing tarpit.

                                    I’m very aware of the turing tarpit, and it simply doesn’t apply here. A lack of redundancy is not the problem – it’s the lack of structure.

                                    Not only we don’t need two kinds of paths, the whole use statement is unnecessary. We don’t even need if. Smalltalk could live without it. We don’t really need anything more than a lambda and a Y combinator or one instruction.

                                    Reductio ad absurdum? If you think it’s silly to question why we have both if-then-else and match, why not add ternary operators, too?

                                    It required a full match on every single Option. It was a pure minimal design, and I can tell you it was awful.

                                    Pattern matching on options is pretty much always wrong, regardless of the minimalism of design. I think the only reasons Rust users use it is because it makes the borrow checker happy more easily.

                                    I’ve used Rust v0.5 before it had if let, before there was try!(). It required a full match on every single Option. It was a pure minimal design, and I can tell you it was awful.

                                    In my experience, the difference in convenience between Rust 5 years ago (which I use for my own projects) and Rust nightly (which is used by some projects I contribute to) just isn’t there.

                                    There is no real point in upgrading to a newer version – the only thing I get is a bigger language and I’m not really interested in that.

                      3. 1

                        This discussion suffers from “Monday morning quarter backing” to an extent. We now (post fact) know which releases of Rust contained more churn than others. “churn” being defined as a change that either introduced a different (usually better IMO) way of doing something already possible in Rust, or a fundamental change that permeated the ecosystem either to due to being the new idiomatic way, or being the Next Big Thing and thus many crates in the ecosystem jumped in early. Either way, my code needs to change due to new warnings (and the ecosystem doesn’t care for warnings) or since many crates are open source I’ll inevitably get a PR to switch to the new hotness.

                        With that stated, my actual point is that Rust releases every 6 weeks. I don’t know if the next release (1.43 at the time of this writing) will contain something that produces churn or not without closely following upcoming releases. I don’t know if the release after that will contain big changes. So I’m left with either having to follow all releases (every 6 weeks), or closely follow upcoming releases. Either way I’m forced to stay in tune with Rust development. For many this is fine. However in my industry (Government) where dependencies must go through audit, etc, etc. It’s really hard to keep up with. If Rust had “major” (read churn inducing releases) every year, or say every 3 years (at new editions) that would be far, far easier to keep up with. Because then I don’t need to check every 6 weeks, I can check every year, or three years whatever it may be. Minor changes (stdlib additions, etc.) can still happen every 6 weeks, almost as Z releases (in semver X.Y.Z speak), but churn inducing changes (Y changes) happen on a set much slower schedule.

                        1. 2

                          When your deps updated to ?, you didn’t need to change anything. When your deps started using SIMD, you didn’t need to change anything. When your deps switched to Edition 2018, you didn’t need to change anything because of that.

                          Warnings from libraries are not displayed (cap-lints), so even if you use deprecated stuff, nobody will notice. You could sleep through years of Rust changes and not adopt any of them.

                          AFAIK async/await was the first and only language change after Rust 1.0 that massively changed interfaces between crates, causing a necessary ecosystem-wide churn. It was one change in 5 years.

                          Releases are backwards compatible, so you really don’t need to pay attention to them. You need to update the compiler to update dependencies, but this doesn’t mean you need to adopt any language changes yourself.

                          The pain of going through dependency churn is real. But apart from async, it’s not caused by compiler release cycle. Dependencies won’t stop changing just because the language doesn’t change. Look at JS for example: Node has slow releases with long LTS, the language settled down after ES2016, IE and Safari put breaks on language evolution speed. And yet, everything churns all the time! People invent new frameworks weekly on the same language version.

                      4. 13

                        Does being idiomatic matter much? The author could just choose not to update their codebases to the latest style unless there’s a big benefit (in which case, why the gripe?)

                        1. 1

                          I’m teaching myself rust, trying to learn how to write idiomatic rust (or at least rust that doesn’t involve arguing with the lifetime/borrow checker constantly…).

                          Lets look at the idioms around async/await.

                          So, does changing idioms matter?

                          • There are fewer examples of best practises to learn from. I need to throw out all examples/documents/blog posts written more than about a year ago, as they generally don’t consider async/await. This drastically reduces the volume of examples/documentation that is useful.

                          • Some code hasn’t been ported to the new idiom. So I need to write conversions myself. For example recvmsg/recvmmsg, I’m now writing async wrappers myself.

                          • While I have read the fine manual, and understood how the various mechanisms work, I’m writing wrappers based on first principles which I suspect are much more verbose than they need to be, and probably I’ve overlooked some issues that I’ll not discover until later.

                          • My code base isn’t consistent. As I’ve learnt things, new code is written using better idioms. There isn’t a lot of clear documentation recommending those idioms yet, so I’m spending more time than I should revising old (functional) code to try and keep my program understandable.

                          • As new idioms (or libraries) come along, I can rip out a lot of code and replace it with better centrally managed code. I can avoid doing so, as rust is generally backwards compatible, but that leaves my code being more difficult to maintain in the future.

                            • Code you use because it “just” works is an asset. Code you need to maintain is a liability. (h/t to @cks for this)

                          I suspect much of this applies to failure/fehliar/anyhow/snarfu/etc (although I’ve not gone digging through them to find out). In fact, I’m avoiding using any advanced error handling system until there is more agreement as to which error handling system is actually useful.

                          1. 1

                            So I for sure understand the issue if you’re trying to learn “the best way to do X” and that keeps changing, but that’s not really the situation if you already have a working artefact that uses “the old way to do X”.

                            I think learning something that is still under active development is just hard. Those developing async/await won’t want to slow down development for the fairly small number of people who are trying to learn the latest method, they’ll just want to develop and find a great solution, then standardise on that.

                            Once something seems more stable, learning materials and library support will come, but until then I think the intended audience is experts and brave novices :)

                            Yes, if you’ve written a bunch of code that you’re not very confident in and you’d prefer to take a dependency on some shiny new library instead, that can cause you to have to update which idioms your code uses. But if you do that you’re paying a cost for a reward. If the reward isn’t high enough, don’t pay the cost. If switching to the new idiom doesn’t buy you enough, then don’t do it.

                            The only case this doesn’t cover is if you think better libraries would have been produced for the old idiom if the new were not available, but it’s hard to know that. Maybe the new, better, libraries were only made possible by the new idioms (either technically or socially).

                        2. 9

                          I found some insightful reactions to this on other forums, including this one by @burntsushi or this one by @steveklabnik

                          edit: fixed link

                          1. 5

                            the first link points to a webpage selling an used thinkpad… and the price isn’t even that good

                            1. 2

                              Thanks for catching that, I fixed the link :)

                          2. 7

                            Implicit wrapping in Result α β using exception terminology? Does “R” in Rust officially stand for “rococo” now? ;)

                            Anyway, being idiomatic is overrated. A funny thing in multi-paradigm languages, community opinions on idiomatic code often shift over time even though the language is not changing.

                            1. 7

                              As a counterpoint - and perhaps my opinion doesn’t matter since I don’t use Rust for work or to make any money - but I’m actually thrilled by the rate of development and release cycle. I recently picked up a Rust project which I hadn’t touched for ~6 months and was able to quickly update the code with the help of cargo clippy and cargo outdated.

                              1. 5

                                Seems to me like C++ changed more between c++11, c++14, and c++17, than rust in its entire post-1.0 lifetime. ? vs try! is a very small detail, and async/await is the only actual big change imho. Who cares about being idiomatic on the latest release anyway? Just have rust2018 valid rust code and you’re good…

                                1. 5

                                  I have to agree at one point and disagree on another. And this will get a bit hand-wavy. Why ? Because if I look at projects running since 2015 on my server, getting used till now, then I’ve got to say: I haven’t gotten any problems to just let them run and compile. I upgraded my last code form try!() to ? syntax only half a year ago.
                                  But if I try to stay on the train, being up to date with the ecosystem it can get really fast. I’ve got hand-made error types in my oldest project, error-chain in my second oldest. Failure in my more recent ones, and snafu in my newest library. And all of them are nice. But I’ll have to migrate some code from Failure to anyhow to stay on a maintained crate. I want to migrate everything else over to snafu or anyhow, because this way it feels better and I’m up to date. So the amount of changes are rapid. My non-asnyc/await code still requires a rewrite of ~15KLOC.
                                  But and that is the big but: Only because I want to be up-to-date, because I want to know that I’m using whats currently accepted as the best, up to date solution. Not because I have to. That old futures-0.1 stuff still runs fine, my old 2015-edition code still compiles and runs. Though, who can blame me for wanting to be up-to-date, for knowing what’s right in rust, what is the most idiomatic way of doing things ? Because otherwise I could have also just go back to writing my stuff in java/c/php. Over there it’s (mostly) plain boring and nothing will change.

                                  1. 4

                                    Please note the guidelines for the extra text box contents when submitting stories on lobste.rs, as explained in the “Submit Story” link:

                                    Please don’t use [the text box] to promote the story, summarize the post, or explain why you posted it.

                                    And additionally elaborated further down, after expanding “Story submission guidelines” (emphasis mine):

                                    When submitting a URL, the text field is optional and should only be used when additional context or explanation of the URL is needed. Commentary or opinion should be reserved for a comment, so that it can be voted on separately from the story.

                                    I know it’s hard to resist, I myself find it hard, but it really helps to give the post a chance to speak for itself, and to let the readers have their own opinion, without coloring it by the submitter’s opinion.

                                    1. 1

                                      Thank you for clearing that up, I was not aware of the guideline. Unfortunately, I can not edit the post anymore.

                                      1. 1

                                        I’ve removed it. No worries.

                                        Thanks to @notriddle for the ping.

                                    2. 3

                                      @klingtnet Next time, please add your own comment regarding the story in an additional comment on your submission next time.

                                      1. 4

                                        Fehler is not idiomatic Rust. Rust is packed with sharp tools you should rarely use. But if you use features in a judicious way that is mindful of long-term implications for things like how much time you spend performing refactors or debugging in a real codebase, Rust can be so beautiful.

                                        Don’t put too much weight into what’s being hyped. The hyped stuff in the ecosystem is usually written without many considerations of real-world usage, because it’s being written by people who have time budgets for hyping it in the first place.

                                        “Experts write baby code.” - Zarko Milosevic

                                        1. 1

                                          It’s interesting to me the difference between coding, good coding, and idiomatic coding.

                                          I remember four or five years ago writing some sample code in F# to demonstrate some concept. Oddly enough, and without my expecting it, I got pushback from the F# community. Why? Because my code was not idiomatic.

                                          Look, I’m a nice guy. I like everybody. But if you’re going to start telling me my code is tested, compiles, works as it should, yet is inadequate because it doesn’t meet some coolkids shifting style guide, I very well may invite you to have carnal relations with various members of your progenitors or their farmyard animals.

                                          I understand that things like syntactic sugar are extremely difficult to get right the first time around and should change. I also acknowledge the role fashion plays in coding whether we like admitting it or not. I fear, however, that we take coding idiomatically far more seriously than we should. But perhaps it’s a much better endless argument than tabs vs. spaces, right? “Bikeshedding” nails it.