From a language architecture standpoint and not an ecosystem standpoint, what might be some things where you’d really not want to use Rust, either because of some limitation that prevents it from doing it or just because it’d be massively annoying to write to the point of significantly reduced productivity? What about Rust makes it unsuitable, and what language paradigms are the best for it?

I hear a lot about how the things that Rust is not good for, JIT compilation with a garbage collector is usually the best solution, and vice versa. How true is this?

  • southerntofu@lemmy.ml
    link
    fedilink
    arrow-up
    4
    ·
    3 years ago

    Rust is really bad with global side-effects from one object to another. In some regards, Rust is a really good object-oriented language (in the “original” definition) because it has strong typing guarantees, first-class interfaces (traits) and the best (de)serialization library i’ve ever encountered [0].

    But Rust being parallel-friendly by default will prevent you from all sorts of patterns common in dynamic languages (JS, Python, PHP), where all objects hold mutable references to any other object (without clear hierarchy/interface) and anything can be mutated from any part of the program. In single-threaded programming, this kind of object tinkering can lead to unexpected behavior (not undefined behavior) where one tiny function somewhere will have crazy side-effects that will break some other part of the program. But in parallel programming, it’s certain to cause all sorts of quirks due to race conditions (two threads accessing/modifying the same data).

    In that sense, Rust takes some inspiration from functional programming, and side-effects are declared with mutable pointers (&mut Type). So it’s still technically possible to do everything you do in a dynamic language in Rust, but the language doesn’t make it especially easy. I personally think it’s a very good trade-off. Although i’m sometimes bored to write more boilerplate, i can’t stress enough how relaxing it is to have your code working expectedly as soon as it compiles. It feels like a superpower.

    [0] serde. Seriously, serde is so powerful and standard across the Rust ecosystem that writing serialization code in golang/python feels very clunky after trying that out.

    • Ephera@lemmy.ml
      link
      fedilink
      arrow-up
      5
      ·
      3 years ago

      Yeah, GUIs in general are messy, almost by necessity. And Rust has a strong focus on correctness, which does not mesh well with messy.

      As an example, it happens that you don’t yet have a certain value that’s supposed to be shown in the GUI, but it also doesn’t matter, because that GUI element isn’t actually visible yet.
      In many typical frontend languages, you would set that to null and be done with it. Rust doesn’t have null and while you can make everything an Option-type, that’s relatively clunky, for how commonly you need such a workaround.

      Obviously, though, constantly throwing around null isn’t great either. The compiler cannot help you at all anymore.
      So, I am still hoping that a new paradigm emerges out of all of this, which is better for GUIs in any language. Basically put more thought into actually resolving the issue, rather than standardizing on the dirtiest workaround.

        • pinknoise@lemmy.ml
          link
          fedilink
          arrow-up
          2
          ·
          edit-2
          3 years ago

          Option is rust’s null. And matches are everywhere because of it.

          And if let’s - so what?

          C++ makes working with null pointers so beautiful.

          How? You still have to check wether it’s NULL or not.

          Businesses want reliable software

          No they want quick turnaround, so they can make more profit. Thats the opposite of reliable software. Thats why most commercial software is such a buggy mess.

          • southerntofu@lemmy.ml
            link
            fedilink
            arrow-up
            2
            ·
            3 years ago

            How? You still have to check wether it’s NULL or not.

            I think that’s the parent’s point: in C/C++ you don’t have to deal with null. You can just pass it around and potentially start unintended/undefined behavior. While in Rust, it’s a compile-time error if you don’t unwrap the option somehow (eg. if let Some(content) = optional_content).

            So yes it’s more concise and “beautiful”, but you’ll probably bite your own hand at some point playing this game

            • pinknoise@lemmy.ml
              link
              fedilink
              arrow-up
              3
              ·
              3 years ago

              How is it more beautiful? You have to deal with null pointers when you want to use the pointer anyway, if you don’t you will get a runtime error, or worse, your program will keep running in an unintended state.

              • southerntofu@lemmy.ml
                link
                fedilink
                arrow-up
                2
                ·
                3 years ago

                yes, that was exactly my point. You can just use a pointer without checking it, which is aesthetically more pleasing, but will produce garbage :)

        • Ephera@lemmy.ml
          link
          fedilink
          arrow-up
          1
          ·
          3 years ago

          I mean, for what it’s worth, my own definition of ‘beautiful code’ includes the properties “reliable” and “human-readable/-writable”. I do not like clever code or code that hides errors away.

          I do work in a company, not in academia, but even for my personal projects, that’s my goal. It’s just a necessity when you want to collaborate with others or your future self.

    • brombek@lemmy.ml
      link
      fedilink
      arrow-up
      2
      ·
      3 years ago

      Rust kinda sucks for writting windows guis. This guy at microsoft spent like two years making bindings and you ended up needing to use unsafe everywhere.

      This looks like a big one and common theme. You can in theory wrap any C API with Rust but it does not mean it is possible to make it safe in Rust - the programming models may be incompatible. Worst is that in C you can use different practices around “ownership” of objects and mix them up in single program - this will make it very difficult/impossible to wrap it in safe Rust and waste a lot of time trying.

      It would be good to have some good practices around this so people can recognize what is worth wrapping and what is better done from scratch in Rust.

    • AgreeableLandscape@lemmy.mlOPM
      link
      fedilink
      arrow-up
      2
      ·
      3 years ago

      Rust does not like undefined behavior.

      Can you elaborate this? Is it like when your program wants an integer between 1 and 5 and it gets -420?

    • basiliscos@lemmy.ml
      link
      fedilink
      arrow-up
      0
      ·
      3 years ago

      Rust kinda sucks for writting windows guis.

      Of course it sucks, as rusts borrow cheker is intrusive and programmatic, whilst in C references to entities are mxied (i.e. sometimes caller owns, sometime framework etc.) and conventional (i.e. you have to read docs in API to know what you can/should do with a reference).

      I consider rusts intrusivness is a weak point, and it’s programmatic checking of ownership is strong point.

      So, if you have a mixture of two worlds (C and Rust), it might be a pain to have such an achitecture. For simple cases, of course, there are no big issues, but things like GUI are not simple things, that’s why Rust is still not here, IMHO.

  • Dessalines@lemmy.ml
    link
    fedilink
    arrow-up
    4
    ·
    3 years ago

    On the garbage collector point: I used to do java professionally, and it made me never want to use any garbage collected language ever again.

    I have some nightmare stories… one giant monolithic program was so bad on memory, that after running for a few days, it would take up all the memory of a 24 GB machine, and one of our devs had to manually write a ton of code to garbage collect certain things just to keep the thing alive.

    Even small programs in GC languages have that problem: they can never really be smart enough to know which data can be scrapped, and do the safest thing, which is to keep it all in memory. Even a simple java program I wrote a few years ago grows to fill up the memory of the 1gb box I have it on, after it runs for a few weeks.

    Rust doesn’t have that problem, as it forces you to think about borrowing, stack and heap from the very beginning. When you realize its not that much more work to do so, you can see why go and java will never beat rust on memory performance.

    • pinknoise@lemmy.ml
      link
      fedilink
      arrow-up
      2
      ·
      3 years ago

      Rust doesn’t have that problem

      That’s a bit generalized you can leak memory in rust e.g. by keeping around old Weak pointers, also std::collections::* don’t shrink by themselves.

  • LLVMcompile@lemmy.ml
    link
    fedilink
    arrow-up
    3
    ·
    3 years ago

    I feel like Rust isn’t good for anything that has unsafe in it, or anything that needs to call in C++ code (like the extended LLVM API).

    • southerntofu@lemmy.ml
      link
      fedilink
      arrow-up
      2
      ·
      3 years ago

      Why is rust bad for unsafe? Isn’t that like a superpower to be able to “override” the borrow checker on a specific line instead of having a whole unsafe codebase?

  • iagev@lemmy.ml
    link
    fedilink
    arrow-up
    1
    ·
    edit-2
    3 years ago

    It’s pretty lousy for exploratory programming, where you load your current application to memory, then start adding a new function onto it, hot reloading on every change and testing your changes and external interfaces in the REPL. Rust’s best approach to this seems to be evcxr, which is quite janky. So in practice you probably end up writing unit tests or dummy binaries that replicate similar behavior.

    Examples of language implementations that are good at this: python (especially with ipython), most common lisp implementations.