1. 29
  1. 9

    Why is the language causing so much pain voted as “the most loved language” for like 7 years in a row in the Stack Overflow survey. Is it the Stockholm syndrome? Do Rust devs like pain? Or maybe it’s a huge cult: you get in and you try to lure in as many people as you can so they feel the pain too.

    Yes, a cult is exactly what it is. Or to put it in less aggressive terms, people who haven’t used Rust and like what they’ve heard of it ; i.e. hype. It’s exactly the same phenomenon that caused Neovim to be the most loved text editor while also being one of the least-used ones in the most recent survey. The stackoverflow survey is a really bad datapoint IMO.

    I also wouldn’t agree with the “Rust isn’t hard as long as you don’t write libraries” conclusion. Programming is writing libraries, even if you don’t neatly separate them out into their own crate. I do agree with the idea that most articles about Rust, whether they praise or criticize it, lack context that would enable a better conversation though.

    1. 8

      “Most loved” is just “% of people that have used it and want to keep using it”, so it’s very explicitly not “people who haven’t used Rust and like what they’ve heard of it”

      1. 4

        I should have been more precise in my choice of words, by “people who haven’t used Rust” I meant “people who haven’t used Rust in any deep, extended of meaningful way”. It’s not rare for people to answer “yes” to the question “have you used X” even if the depth of their experience is limited to using X for a 50-lines program.

        As an example, if I was answering the stackoverflow survey I would say that I have used Rust (I wrote an interpreter for an esolang and a Neovim GUI in it, maybe 3000 lines in total?) and that I would like to keep using it, but I also wouldn’t consider my answers about Rust as interesting since my experience with it is very limited.

        1. 4

          I think you’re projecting a lot of assumptions not in evidence onto a very straightforward survey question.

          “It’s a cult because I assume everyone or at least a highly significant percentage of people who said they’d used it and would like to keep using it, have in actuality barely used it. No I don’t have any actual data backing this up, why do you ask?” doesn’t exactly sound like much of anything other than reasoning from sour grapes and solipsism.

          1. 2

            No I don’t have any actual data backing this up, why do you ask?

            The data I am using to infer that Rust hasn’t been used a lot is the amount of Rust job offers available, compared with other programming languages such as C++ or JavaScript. To me this is an indicator that Rust hasn’t been used in a lot of industrial settings yet.

            Another datapoint I have is issues like these: https://github.com/neovim/neovim/issues/8669 . These RIIR proposals often come from people who have little to no experience at all with Rust, if you look at their Github profiles.

            I’m not saying that nobody uses Rust in anything that matters (Mozilla has been shipping Rust code for 5 years) or that you necessarily end up hating Rust when you actually use it (every mozillian experience report I’ve read is extremely positive). I’m saying that there is a lot of hype around Rust and that the engineers answering the stackoverflow survey probably don’t have as much Rust experience as what we would want in order to consider their experience a useful datapoint.

            I think Rust is a huge improvement on the state of the art, and I like it, but denying the hype around it is wrong in my opinion. It set ups people with wrong expectations and will result in disappointments (I’ve seen this happen in a couple of colleagues, who usually are fairly good at ignoring hype).

          2. 1

            The question used to form the metric was:

            Which programming, scripting, and markup languages have you done extensive development work in over the past year, and which do you want to work in over the next year?

            50-line programs do not qualify as “extensive” development work.

            Also, a personal anecdote: I know several people who write Rust for their day jobs, and they love it.

            1. 1

              Oh, interesting, this is not how I remembered the question. This means that I was wrong and the stackoverflow survey is a valid datapoint after all.

              I know several people who write Rust for their day jobs, and they love it.

              I did not deny their existence, I just (wrongly) asserted that they weren’t as many as we thought they were :).

        2. 3

          I also wouldn’t agree with the “Rust isn’t hard as long as you don’t write libraries” conclusion. Programming is writing libraries, even if you don’t neatly separate them out into their own crate.

          Not all libraries are equal. As someone who likes Rust and uses it daily, Rust can be very difficult for making libraries for general consumption, but relatively easy when libraries are made for a smaller audience (i.e. company internal). There a ton of API level decisions that have wide ranging trade-offs and constraints on they place on their consumers, many of which aren’t immediately obvious. The more generic solutions to those constraints become increasingly complex and introduce even more API surface points that could have unintentional affects.

          1. 3

            Rust can be very difficult for making libraries for general consumption, but relatively easy when libraries are made for a smaller audience (i.e. company internal)

            I haven’t yet written nearly enough public-facing Rust to know if this is indeed the case. I haven’t hit that threshold yet. But if it is, I think this is further enforcing @glacambre’s point about hypes (which my internal jury is still torn on FWIW). “Can be difficult for making libraries for general consumption, but relatively easy when libraries are made for a smaller audience because it’s difficult to make constraints” can be quite easily shorted to “is not very good at building generic, reusable models”.

            That’s really not a good thing for a programming language to suck at. Libraries for general consumption, especially large ones, are exactly the things I don’t want to make myself. I sort of trust myself to roll out my own ELF header parser or whatever. It’s those damn large libraries like, I dunno, the Qt framework, which I am more than happy to let fifty-people teams of well-paid engineers to handle, especially since it’s unlikely that I’ll be able to churn anything like it in a timeframe of less than a decade or so.

            Besides, I really don’t want to write libraries for a small audience! If I’m going to write code that I will release publicly, I want it to help as many people as possible, not just my colleagues. And if it’s code that others wrote, I am the damn audience. The whole point of having a rich set of libraries is for people not to have to roll their own. If every company writes their own company internal libraries for everything, you don’t have a rich set of libraries, you got Common Lisp cca. 2004 all over again.

            I swear to God if Rust really sucks at this and I just wasted like a year’s worth of evenings trying to get proficient at it and five years from now I’ll still have to write C++, I am so quitting this stupid programming thing.

            1. 5

              I don’t think writing Rust libraries is harder due to composition – if anything Rust libraries are easier to compose IMO, because they use composition instead of inheritance you don’t run into a weird situation where, e.g., an object needs to be the child of two different libraries’ parent classes or something like that. You just stick two things in a struct, or implement two traits, or whatever, all’s good.

              The thing about Rust that makes libraries more difficult is the number of things you want. For example if you’re implementing a hash table in, say, Python, the API interface probably looks like:

              class HashTable:
                  def get(self, key): ...
                  def set(self, key, value): ...
                  def iter(self): ...
                  # maybe some others
              

              whereas the equivalent in Rust is at least:

              trait HashTable {
                  fn get(&self, key: K) -> Option<&V>; // regular immutable access
                  fn get_mut(&mut self, key: K) -> Option<&mut V>; // mutable access for changing the value
                  fn set(&mut self, key: K, value: V);
                  fn iter(&self) -> impl Iterator<...>;
                  fn iter_mut(&mut self) -> impl Iterator<...>;
                  fn into_iter(self) -> impl Iterator<...>;
              }
              

              and that’s not getting into ZSTs, thinking about object safety for dyn, panic safety, no_std, async, etc… these things force you to think about aspects of your library, like allocation, that other languages don’t.

              Because of no_std, a lot of Rust libraries will divide themselves into a part that requires allocations, and a part that doesn’t, so that part of the library can be used without a system allocator. Python, Golang, etc. libraries don’t have to think about that (though C{,++} and Zig do!). Because of object safety, you sometimes need to think about what parts of your traits require a sized return type, and which don’t (and can be annotated Self: ?Sized), if you want to support trait objects. In a lot of languages (even systems languages like C++!), everything is behind a pointer and has a vtable and thinking about that isn’t needed.

              That all said, once you make a nice library interface it’s generally a joy to use, and I find libraries in the Rust ecosystem tend to be quite flexible, reusable, and high quality. But there’s a lot of concerns to think about, and Rust libraries do tend to churn their API in pre-1.0 versions while they work towards something that handles all the concerns in a nice way.

              1. 2

                Yeah, I can’t say I’ve hit a threshold where I found it difficult to write reusable (i.e. library) code past a certain size, or past a certain size of an implied audience – but I’ve not written enough Rust code, either, hence the “yet” in my prior post :-).

                I think it’s a given that a model that requires you to explicitly formulate data access constraints (mutable/non-mutable, unique/shared ownership etc.) will result in more verbose code than one which can leverage a GC, like Python’s, but that’s a trade-off that’s always been there. IMHO the higher churn generated by the more diverse API is a trade-off worth making. The C++ API interface for a hash table would be closer to the Python version, but the smaller footprint isn’t free: you pay for it with ever-multiplied head scratching at the user end about whether each function is thread-safe or not. And if you want an implementation that’s as fast as possible in the more favourable cases (e.g. immutable access) without relying on intimate compiler knowledge (which tends to backfire in wider settings) you wind up with a wider API.

                Similarly, API churn in pre-1.0 libraries has always been a thing. You rarely get code that can be productively interfaced in practical settings just by copy-pasting functions from a program. Unless you’re doing something that’s well-understood (like a hash table) there’s bound to be some trial and error.

                Maybe API churn rate is a little higher in Rust but I think part of that will stabilise in time. Some of it is due to the high language blog/evangelist/fan post churn, a phenomenon we all know and loathe from C++ land, where every new standard version brings out a flurry of “here’s how you should now do ”. That’ll never die out, but as more people develop their own idioms and write more real-world code and fewer toy programs, more of it will be ignored. And, of course, some of it is just because the language is still relatively young and idioms are still being developed. That tends to quiet down in time.

        3. 5

          Programming can be both:

          • exploration of the solution space of a problem, trying out different approaches to see which set of abstractions best fits, or even seeing if the approach you had in mind is possible
          • producing “production” code which needs to be as correct as you can make it

          Some languages make the first easier, some the second. (Would appreciate views on langs which successfully optimise for both).

          As an industry, perhaps we have a problem where people take the result of the first process and ship it as their answer to the second.

          1. 4

            It seems we need, Rust - The Good parts book now :P Community consensus on how to write properly without using too much. Basically PEP 8 for Rust.

            1. 1

              Lol, “Effective C++” by Scott Myers used to be the poster child – the “morality guide” for a language. Telling you which parts to use and which not to.

              Heck, even “The Good Parts” is a pretty old historical throwback now.

              1. 1

                “Effective C++” by Scott Myers

                Ahh, those memories :P

            2. 2

              [heads up, halfway through writing this I realize I haven’t use rust in over a year, and it is possible for software to change when given time :) ]

              My old experience attempting to use async code in rust only really hit one thing that I consider to be an actual problem, everything else is a reasonable consequence of the language/type system design.

              The thing I found to be a problem was that while making a function async is easy, for some reason you can’t actually use async functions from rust. The first thing you need to do is find some crate that can run the async functions for you - alas I have forgotten what these are called :(

              At the time I was trying to learn rust it was still relatively new, but my experience was not only having to find what crate to use, needing tutorials on how to launch those crates and get them to actually run my code.

              I think complaining about what I’m going to call the ergonomics of sharing state is kind of missing that that is what you’re doing, and rust doesn’t like sharing state between functions in single threaded code, why would you expect different in multithreaded. I do agree that the ergonomics suck, but those ergonomics are specific to async or multithreaded rust in general. Maybe some sugar to ease sharing immutable state would be nice, but for mutable shared state the current syntax matches the syntax for shared mutable state in sync code as well.

              1. 1

                Take a look at https://github.com/smol-rs/smol to see what comes together to make an async runtime in Rust.