1. 11
    1. 75

      This is a low-effort hit piece with scattered thoughts, poorly backed. Not worth your time.

      1. 10

        I wouldn’t have called it a hit piece, I agree that it’s not especially well organized, and I have no idea how much effort the author put into it. But I strongly agree that it is poorly backed. Most of it leans on the author’s belief that WebAssembly is the future of software.

        While I’m also unwilling to speculate on the level of effort that went into that piece, I will observe that it should read very familiar to anyone who was paying attention to this sort of thing in the mid-1990s. If you replaced every instance of “WebAssembly” with “Java” or “the JVM”, all of those points were made in similar ways in the mid-1990s (and were so widely believed that MS ran off and created .Net in the early ’00s) and have not aged well.

        1. 7

          If I understand you correctly, you’re saying it’s about the right time for me to create a new version of XML and make bank as a consultant selling it to the enterprise.

          1. 4

            If you miss the billable hours from getting different SOAP stacks to interoperate, JSON Schemas seem well-suited to enterprise consulting.

    2. 34

      More broadly, Rust’s complexity makes Rust harder to learn, which is an unnecessary burden placed on those learning it.

      My experience learning Rust has near-universally been positive in this regard. Most complexity exists for a reason, and in the end I’m happy it’s there because it makes the Rust experience dramatically better than Go. Of course Rust does have some things that are just awkward and obnoxious for little benefit, but many of those have gone away as Rust continues to mature. Picking up Rust 5 years ago was much harder than it is today.

      If in 2050, programmers are sitting around waiting for their Rust code to compile just to be told that we failed to sacrifice enough to appease the borrow-checker gods,

      cargo check?

      1. 19

        Most complexity exists for a reason

        It is extremely comforting to assume this, but I believe most complexity exists because someone couldn’t (for time, brains or money) make it less complex.

        If you have the time, it is usually worth thinking about how to reduce complexity, instead of accepting it and assuming it “exists for a reason”, because if you can find a way to reduce complexity, you will free your brains and money to do work on other things.

        I am aware there are people who just like being busy and like working hard. Those people love complexity, and there’s little you can do about that except not believe them and talk about other things besides programming.

        And listen, I don’t mean that this is the necessarily case with rust[1], only that you (and others) shouldn’t be so accepting of complexity thrust upon you because there are things you can do about it.

        [1]: …although I do happen to think so, I’m also aware this is just my opinion. If rust makes you happy, be happy!

        1. 22

          only that you (and others) shouldn’t be so accepting of complexity thrust upon you because there are things you can do about it.

          I think it’s pretty clear I was talking about complexity in Rust, and I resent the implication that I blindly accept complexity without any sort of critical thinking.

          Rust the language does have a lot of up-front complexity. But that complexity comes with up-front safety and correctness. It’s compiler errors vs core dumps, it’s borrow checking vs pointer aliasing bugs.

          I once spent 2 weeks chasing a pointer aliasing bug. After pouring over thousands of lines of code, customer provided core dumps, and live debugging sessions once I could reproduce the issue, I finally noticed that two pointers had the same hex value when they shouldn’t have. It never caused a crash, never corrupted data, only reduced throughout in a certain edge case. And it would have been a compiler error in Rust.

          Unsafe languages aren’t actually less complex, they just push the complexity down the road.

          1. 7

            Unsafe languages aren’t actually less complex, they just push the complexity down the road.

            I don’t think I can agree that all things are equally complex. I hope this is not what you mean, but if it is not what you mean, I cannot understand why you would say this.

            We have to choose where we want our complexity, for sure, and like entropy it cannot be avoided completely and get any work done, but some things are more complex than others for all kinds of complex things.

            I think it’s pretty clear I was talking about complexity in Rust, and I resent the implication that I blindly accept complexity without any sort of critical thinking.

            I am very sorry that I have offended you in any way, however if you think that you never have accepted complexity in your life, without, (as you say) “any sort of” critical thinking, then you should probably think whoever changed your diapers when you were a child. We all do it, and there’s nothing wrong with it sometimes.

            I just think it’s something we programmers should watch out for- like our own invisible biases, or getting value alignment before asking someone to review our work. If we think we don’t do it – or we get offended at the implication that we’ve done it, we can be blind to something that if we had discovered in other circumstances (or as they say, with different priors), that we would find very important.

            It is awful hard for me to convince myself that rust represents the best we can do at anything in particular, only perhaps the best we have done so far at some things, but so what? I feel that way about a lot of languages. If rust makes you happy, I think you should be happy as well!

            1. 9

              PLT person here. Outside of async (which I haven’t used much but hear is very complex), Rust has very little accidental complexity. If you make a language with borrow checking, ADTs, traits (interfaces), and emphasis on zero-cost abstractions, it will necessarily have most of the complexity of Rust.

              1. 2

                Yes and no. There’s a bunch of choices in Rust to make things implicit, which could have been explicit. This somewhat reduces the syntax one needs to learn at the cost of making it much harder to understand the text of any given program.

                1. 3

                  That’s funny, I think of Rust as being an unusually explicit language. Which things are you thinking of? My list would be:

                  • Automatic dereferencing and automatic ‘ref’ insertion in pattern matching and automatic ‘.drop()’ insertion. Though the language would get very verbose without these.
                  • A couple auto-derived traits. Though again, it might get really old really fast if you had to write ‘#[derive(Sized)]’ for all of your types.
                  • Functions that return a type not dependent on its argument, such as .into() and .parse().
                  • Operator overloading
                  • There are a couple “magic” fat-pointer types like &str

                  Things that are explicit in Rust but often implicit in other languages:

                  • No implicit type coercions like in C or JS
                  • VTables are marked with ‘dyn’
                  • Semantically distinct values have distinct types more often than in most languages. E.g. String vs. OSString vs. PathBuf.
                  • The “default” import style is to name all of your imports instead of using globs.
        2. 8

          It is extremely comforting to assume this, but I believe most complexity exists because someone couldn’t (for time, brains or money) make it less complex.

          I think this is often true. But also, a ton of complexity totally has reasons for existing. It’s just that the linear benefit of simplifying one use case is generally outweighed by the exponential downside of combinatorial complexity of the language.

          Go didn’t manage complexity by coming up with a smarter simpler language design - they managed it by giving things up and saying no. The end result is a lot of quality-of-life things are missing in the small, but the standard of living in a large Go code base is, on average, better.

        3. 6

          couldn’t (for time, brains or money) make it less complex shouldn’t be so accepting of complexity thrust upon you because there are things you can do about it

          I think we can all hope that future rust or a successor may come up with a language that provides the same flexibility, performance and safety without the possible* hassle you have when learning rust. But currently there is none (without a required GC, with native compilation, with thread safety, with C-interop that doesn’t suck, with [upcoming] embedded support, with async, with …).

          *Also, I think that many people simply underestimate how much they’re used to the C/C++/Java style of programming, where you either have a GC, have OO or can simply write the code assuming “the compiler will get it” (speaking of stuff the borrow checker currently can’t prove, and thus accept). Or they weren’t actually define behavior in the first place. Something i’ve seen from people trying to port their whacky c-code over to rust, only to find out they simply memory leaked their stuff. Which was fine for the oneshot CLI, but actually never defined or good behavior. On the other side I’ve had students that learned programming the racket way, and then stumbled upon a myriad of complexity when learning java (this vs this@.., static, field init vs constructor init and the order of them, ArrayList vs array vs List, primitives vs Objects vs autoboxing).

          I think it’s a little dismissive to say others didn’t make it as good as they could have, it may be true, but it’s harsh to assume they didn’t try and people are worshiping that.

          1. 3

            But currently there is none (without a required GC, with native compilation, with thread safety, with C-interop that doesn’t suck, with [upcoming] embedded support, with async, with …).

            Quite possible indeed. Zig maybe. Zeta-C. D. I think some of those things are pretty subjective, so maybe others? But in any event, not everybody needs all of those things, and even when people do, they don’t necessarily need them all at once. I think it’s important to keep that in mind.

            I think it’s a little dismissive to say others didn’t make it as good as they could have, it may be true, but it’s harsh to assume they didn’t try and people are worshiping that.

            I think they did make it as good as they could have (with the time, money and brains that they had), only that some of those constraints aren’t anything “reasoning” can do anything about at all. Where do you think I said the opposite?

            1. 2

              they don’t necessarily need them all at once

              That’s maybe true. But on the opposite people program everything in C++ (Embedded, Kernels,Webbrowsers,Servers,Games), everything in JS (Embedded,Electron,WebGL,CLI..), everything in Java (embedded processors, DVD, android and the whole CRUD stack) and everything in C. So if you can get rust high level enough for (web) applications, and opt-in low level enough for embedded (core/alloc) - why not ? I don’t think there are actually quirks in rust that are originating out of the broad range of supported use cases. Obviously you can always make a better DSL for specific use cases, in the way Ruby on Rails is nothing else than a DSL for this. (And then go back to C interfaces when you actually need ML/CompSci/.. )

              Regarding “I said the opposite”: I think it’s a combination of these lines

              I believe most complexity exists because someone couldn’t (for time, brains or money) make it less complex you (and others) shouldn’t be so accepting of complexity thrust upon you because there are things you can do about it

              Though I just wanted to push back the idea that “I” can just do something about, or that it’s only because people were lazy, because that’s one way I can read the above sentence.

              1. 1

                But on the opposite people program everything in …

                I can’t really speak for people who think learning a new language for a specific domain is beyond the brains, money and time they have; I mean, I get there’s an appeal of having one language that can do everything, but there’s also an appeal in having many languages which each do certain things best.

                I don’t really know which is better overall, but (more to the point) I don’t think anyone does, so I urge vigilance.

                I just wanted to push back the idea that “I” can just do something about, or that it’s only because people were lazy, because that’s one way I can read the above sentence.

                I hope you can read it another way now; Of course there is something you can do about it. You can do whatever you want!

        4. 3

          This just depends on your priors. Perhaps in general its a good assumption that reasonable work will eliminate complexity, but in many situations (for instance, almost any situation where people are routinely paying the cost of extant complexity) it may make sense to adopt a prior which leans more towards “this complexity exists for a reason.”

          Rust would be a great example of the latter case. Its a programming language that was intentionally designed to reduce the complexity of programming in domains where C/C++ are used. Since both C and C++ are very complex, its reasonable to assume that design process was complexity focused. And since rust was designed in a commercial context its also reasonable to assume that some skin was in the game.

          These facts suggest that its more reasonable to accept that the complexity in Rust is there for a reason.

          In my career, when I have discovered some apparently complex artifact I’ve almost always found that there were compelling (sometimes non-technical, but nevertheless real) reasons that complexity hadn’t been eliminated.

          1. 2

            In my career, when I have discovered some apparently complex artifact I’ve almost always found that there were compelling (sometimes non-technical, but nevertheless real) reasons that complexity hadn’t been eliminated.

            I think this manages to confuse what I mean by trying to distinguish between “complexity exists for a reason” and “complexity is usually an estimated trade-off between {brains,money,time}” – because for sure the real limitations of our minds and wallets and health are as good a “reason” as any, but I don’t think it’s useful to think about things like this because it suggests thinking of complexity as inevitable.

            These facts suggest that its more reasonable to accept that the complexity in Rust is there for a reason.

            They don’t though. These “facts” are really just your opinions, and many of these opinions are opinions about other peoples’ opinions. They’re fine opinions, and I think if rust makes you happy you should be happy.

            But I for example, don’t think C is very complex.

            1. 5

              C is exceptionally complex, in a couple of different ways*. It is one of the most complex programming languages that has ever existed. I am baffled whenever I see someone claim it is not very complex. Rust is massively less complex than C.

              *: The most relevant one being that in terms of memory management you have actually even more difficulty and complexity in C than the Rust borrow checker, as you have to solve the issues the borrow checker solves but without a borrow checker to do it, and also with much weaker guarantees about the behavior of eg pointers and memory.

              1. 2

                That’s fantastic you have a different opinion than me.

              2. 1

                you have actually even more difficulty and complexity in C than the Rust borrow checker, as you have to solve the issues the borrow checker solves but without a borrow checker to do it

                While it is arguably true that you have to solve the same issues with or without a borrow checker (and I could argue with that, but won’t), it’s definitely not true that the borrow-checker is a magical tool that helps you to solve problems without creating any of its own. You had a memory management problem. Now you have both a memory management problem and a proof burden. It may be that the proof framework (burden, tooling, and language for expressing the proof) helps you in solving the memory management problem, but to pretend that there is no tradeoff is unreasonable.

        5. 3

          It is extremely comforting to assume this, but I believe most complexity exists because someone couldn’t (for time, brains or money) make it less complex.

          I think coloured functions are a perfect example of this phenomenon. For the sake of my argument I’ll assume that everyone agrees with the premise of this article.

          If we compare two approaches to asynchronous code, Rust’s traditional async/await, and Zig’s “colorblind async/await”, I would argue that Andrew Kelley applied the effort to make Zig’s approach less complex, while Rust did not.

          1. 2

            Honestly I think zig’s async/await is a bit of a cheat (in a good way) because it’s not actually async but doing a different, low level thing that can map to “some concept of async”. It’s low level, so you can ab-use it for something else (but please don’t).

            The nice thing about it is that you can really get a solid mental model of what the CPU is doing under the hood.

            1. 1

              Yes. And that low level thing is a theory of our software science, and a compelling one because that one gives you different ideas than the other; Our languages “look” different, can produce many of the same results, but using one instead of another means making different kinds of changes to those things in one language will simply be easier than making those changes in another.

              Software can be so beautiful!

    3. 30

      Overall, I look forward to a future where every operating system, web browser, and WebAssembly runtime is written in (hopefully a simpler variant of) Rust, Vale, or Cone, and where the rest of us can program in some variant of V, Go, or Janet

      This twigged a sense-memory in me, so I checked and yup this was written by @elimisteve, who exclusively posts on Lobsters to harass people who say anything bad about V.

      (For newer members, V is a language that started out making impossible claims, got a huge amount of Patreon funding, and then when @andrewrk and @cadey posted legitimate criticism of the claims, the entire V community went on a warpath harassing them.)

    4. 28

      I’m not a fan of Rust’s design for many reasons. The most frivolous of those is that the attempt to make it look as if it was a C-like language made it look ugly (that’s incredibly subjective of course). Obligatory disclaimer: that doesn’t mean I have anything against people who use it or that I refuse to contribute to projects written in it. I don’t.

      The author, however, seems to have no idea what he’s talking about. If he wants a safe imperative language that covers the same range of uses cases as Rust (including embedded), then we’ve had one since the ’80s.

      If we imagine a world where words like “sum type” and “pattern matching” don’t scare away former C users, there are many more good options for writing fast, secure software. Only a person who looked at maybe 10 most talked-about languages could think that Rust and Go are the only native-code compilers that aren’t C or C++.

      No mention of Swift even! Not understanding that Swift is a “StandardML of Cupertino”? Its documentation writers made an effort to hide that from former Objective-C users for sure. I would have a hard time avoiding calling algebraic types algebraic types. ;)

      Also, isn’t V-lang just vaporware?

      1. 6

        V-lang’s benchmarks are without garbage collection / memory management AFAIK. I’m not sure if the language still has only aspirational memory management. So, it feels like the language is vaporware/unfair since it makes completely unreasonable concessions (memory leaking) to make those benchmarks.

      2. 2

        Also, isn’t V-lang just vaporware?

        I don’t use V, but no.

    5. 21

      The bad news is that Rust will also replace some C and Go code, which will add complexity to the world.

      No this is good news. I don’t actually think C is all that simple of a language to write, especially if you are trying to write C that is guaranteed (with complex external tooling) to be memory safe in the way Rust is by default. Also C’s type system’s and general tooling is very primitive and Rust does a much better job in both respects. The extra complexity of Rust is worth the gains with respect to C. I don’t know Go very well, but from what I’ve heard about it it seems like the language might benefit from a little more language-level complexity, in the name of reducing opportunities for writing code that fails at runtime. It’s gonna be much less likely to justify rewriting a Go codebase in Rust than a C codebase, though.

      1. 4

        I think replacing C code with Rust is good because (as you say) C is insidiously complex and often has security issues. I don’t think the same is true for Golang. I don’t, personally, like the language, but choosing between Golang and Rust is just generic engineering trade-offs. The bar for replacing existing, working Golang code with Rust is pretty high. For new projects, there are cases where the extra safety*, performance or memory footprint is worth the complexity. There are also lots of cases where it’s not.

        * Golang is mostly memory safe if you don’t use the unsafe package. However, it isn’t thread safe and (IIRC) has no memory model for unsafe data accesses.

        1. 6

          The first time I ever used golang I was immediately bitten by a data race because the language encourages pointers everywhere and sharing state is so easy. Definitely put me off a language that advertises being used for concurrency.

          1. 2

            It’s much safer if you just let everything be shallow copied all the time, which I’m pretty sure is how you’re supposed to do it except on the hottest of hot paths.

    6. 13

      If in 2050, programmers are sitting around waiting for their Rust code to compile just to be told that we failed to sacrifice enough to appease the borrow-checker gods

      In 2022, just like last year, you don’t have to sit waiting for the borrow checker to check your code. The only time you really wait for the compiler is when you build a release, and then you already know the outcome.

      Tooling already solved the problem of waiting for the code to be checked. I use bacon, other use rust-analyzer in an IDE setup.

    7. 10

      Having seen quite a few Golang code bases from the Kubernetes ecosystem, I can tell you that Golang doesn’t magically make that kind of code less complex.

      One example is: with goroutines having first-class support, that style of concurrency gets ham-fisted everywhere, even if multiprocessing, async/await, or other concepts would have been better.

      It’s almost like blindly striving for “simplicity” above all is just bad engineering. It’s a resource to balance like everything else.

      1. 3

        It’s a resource to balance like everything else.

        Thank you! This is something that I find is missing from many discussions about the value of x language or tool. Whether choosing your tools or writing code, there are always trade-offs to be made, and choosing carefully for your use case is going to make for the best results.

        That’s one reason I like to read opinion pieces along these lines, because they may help me make better-informed choices: I can’t say this particular piece did much for me, though. I disagree with its assumptions and didn’t see any effort made to change my mind with evidence.

    8. 8

      If I was to argue why rust is not the future of software I would make the following claims:

      • It is a complex monolithic piece of software with no standard and only one implementation.
      • There is reason to believe that our improved understanding of type theory will let us leapfrog rust with better security guarantees and simpler descriptions of programs.
      • Speaking of the descriptions, rust has a complicated syntax, not as complicated as C++, but complicated enough that it is unlikely that someone happens to come up with the same one or a compatible one. In that sense I believe that “rust the syntax” is not the future of software either since I believe we will use nicer ways of writing type signatures.
      • “rust the compiler” is also not the future of software, it does too much in one step. The collection of tools approach in the C world may have just been to try and make C safe after the fact but I believe the future of programming is using the same language and syntax in an interactive, hot-reloadable, repl-style as you then compile with dependent programming and proofs of correctness. The trick is to evaluate the same data in different ways.

      However I think rust is a perfectly fine step on the way towards the future and a sufficient tool for this gap that C++ was not managing to serve sufficiently well.

      1. 2

        There is reason to believe that our improved understanding of type theory will let us leapfrog rust with better security guarantees and simpler descriptions of programs.

        Would love to read more on this!

        1. 3

          I guess the most convincing evidence is something like ATS: http://www.ats-lang.org/

          But it’s what all the smart people are competing to solve so it’s hard to believe no one will ever improve on rust.

          Actually I kinda hope that rust is going to end up in a role like java, monolithic enterprise language with solid platform. The FOSS world is better served by lisps imo (and I realize that this statement is all kinds of stupid but it makes sense to me).

        2. 1
      2. 1

        I think this comment is a better articulated version of what the linked post was trying to achieve.

    9. 5

      Humanity needs the future of software to have the following two properties:

      • Security
      • Simplicity

      But does it?

      Simplicity doesn’t strike me as a quality worth having in itself, but as a tool to attain useful goals such as for example maintainability, performance, correctness, or indeed security.

      That means that you can choose to compromise on simplicity to achieve what you want (eg “Performance, Reliability, Productivity”).

    10. 5

      This article confuses simplicity from a user perspective with the developer experience. One does not necessarily translate to the other. Arguably Rust is quite pleasant in terms of developer experience.

      Disregarding that there are other aspects outside of “simplicity” and security. How about efficiency?

      1. 4

        I think the author doesn’t define simple clearly enough. Similar to the points made in There’s no such thing as clean code. My impression based on context was that they meant, “Rust is not a simple language to jump into from another language”, or, “Rust is not a simple language to prototype applications in”. From that perspective I partly agree with the author - it’s definitely complex to jump into.

        However - once past that point Rust does make writing many types of application simpler than other languages. It makes writing maintainable code simpler, and readable code is simpler. Cleaning up resources is simpler than in some other languages. Making code efficient - to your point - is simpler than some other languages.

    11. 2

      There is quite simply a huge class of software where you probably don’t need a borrow checker. I’m thinking for example CLI tools where you can write it so that the data structures are simple and the memory allocation each step pulls from an arena and gets chucked all in one go, UAF impossible by the structure of the task.

      1. 1

        Sure, if you malloc and never free and leave it up to the OS then rust gains very little.

        1. 3

          You can have iterator invalidation and data races even if you never free anything. You can have UAF memory corruption with on-stack data. Code may have objects that are logically no longer used, even if that is not reflected in memory allocation, and using them can lead to logic errors (e.g. you replace “old” object with a “new” one, but some other code stores data in the “old” leaked/orphaned one — that’s data loss, even if it’s not a crash).

          I still miss borrow checker even in GC languages. In GC languages I need to use defensive coding, and e.g. copy data given to a function to ensure there is no accidental sharing of the data and the caller can’t modify the data unexpectedly later.

          1. 1

            Oh sure, if you’re doing manual threading stuff then that’s useful to. The main draw vs C is for memory management though, since I’ve never done threading in C.

    12. 1

      makes Rust harder to learn … complex software makes our world much more difficult to comprehend

      “We cannot solve our problems with the same thinking we used when we created them.” Albert Einstein.

    13. [Comment removed by author]