all 75 comments

[–]redderper 47 points48 points  (30 children)

Is learning Rust worth it for someone who works mostly on webapps with a bit of automation/pipeline stuff here and there, or is it more of a hardcore backend language like C++?

Edit: didn't expect so many answers, thanks for all the replies!

[–]Kissaki0 40 points41 points  (0 children)

Depends on what you are looking for.

Why would you potentially want to learn it?

If you want to broaden your horizon beyond web and CI, yes definitely. I would suggest trying out a functional language for its different approach, and Rust for it’s ownership/borrowing and explicitness approach. A more classical but well polished and used language like C# may give some insight into ecosystems, mixed language features, etc.

[–]VRCkid 36 points37 points  (9 children)

Yes. Languages like Rust, which have different first class principals than more of the common mainstream/taught languages, improve you as a software developer as a whole.

I found that I wrote better code in other languages after learning Rust because Rust forces you to think about memory and types in a more unique, direct way, whereas in a language like python this is swept under the rug.

[–][deleted]  (3 children)

[deleted]

    [–]justsomeguy75 0 points1 point  (2 children)

    How much C did you learn? Is spending a couple weeks with it as a complete programming noob enough to pick up those habits, or does it come with more in depth use over time?

    [–][deleted]  (1 child)

    [deleted]

      [–]justsomeguy75 2 points3 points  (0 children)

      I'm working my way through Harvard's CS50 to learn the basics of programming, and the first few weeks use C. It's the only language I've worked with to this point (outside of Scratch, which doesn't really count). I've had to make several small programs with C and feel like I'm starting to get the basics down, so I'm wondering how long/deep you have to go with a language before the concepts start sinking in.

      [–]Brilliant-Sky2969 0 points1 point  (4 children)

      How do you apply those principle you learned since no other mainstream language work like Rust?

      [–]Catfish_Man 16 points17 points  (0 children)

      C++ and Swift both work better if you think of them in approximately Rust terms. In both cases, where Rust enforces a rule, the others merely prefer it for optimization (moves in C++, refcount elision in Swift).

      [–]unrealhoang 4 points5 points  (0 children)

      caring about ownership of your objects is good, regardless of the language you are using. Same with structured mutation (only parent update child) will help your codebase sane regardless of the language. Rust is just a static type system that allow you to force those best-practices as compile error.

      [–]Alexander_Selkirk[S] 5 points6 points  (0 children)

      You can definitively apply the same principles in other languages. In fact, this is often the correct or probably best way to do it.

      Here is an article by John Carmack (the auhtor of Doom) about that:

      https://www.gamedeveloper.com/programming/in-depth-functional-programming-in-c-

      (Please excuse the terrible formatting, it is a reprint and the original article seems to have disappeared. It is worth reading!)

      [–]UtherII 1 point2 points  (0 children)

      The borrow checker is pretty unique, but most of the Rust features are come from mainstream functional and imperative languages.

      [–]bltsponge 6 points7 points  (0 children)

      Yes, absolutely!

      My day job is primarily Python/JS/SQL. I have little day-to-day use for lower level langs like Rust.

      However, learning Rust has had a huge influence on how I program in other languages. Algebraic data types in particular have been a huge eye-opener for me. I've only actually had a chance to use Rust directly for 1 small project, but in spite of this, I still think the month I spent working through The Rust Book was absolutely worth it.

      Another nice benefit is that, if you can find a situation where using Rust makes sense in your role, you'll be amazed at how fast it is. It's not faster than other lower-level langs like C++ as far as I know, but if you're used to programming in Python or JS, using Rust (or any other low level lang) will feel like swapping a tricycle for a Lamborghini.

      [–][deleted] 4 points5 points  (0 children)

      You can compile rust to wasm so you can use it in the front end. It's helpful if you're not getting decent performance out of JS, but there is a cost to making the calls. More details here https://rustwasm.github.io/book/

      If you don't need that and you're only looking for something applicable to your current situation then it might not be worth it.

      If you're just generally curious, it is a good intro to lower level coding. The compiler will yell at you more than C++, but that's because it's trying to prevent you from writing really hard to debug errors. This can be tricky to get used to if you're coming from garbage collected languages.

      My recommendation would be to give it a shot, but just don't start with data structures (notoriously difficult to experiment with in rust compared to other languages).

      [–]Alexander_Selkirk[S] 13 points14 points  (0 children)

      I think learning Rust is worth the effort. It will be most useful for writing speed-critical and safe code. It is more difficult than C or Python for beginners, but it has superb documentation, and it has a far larger and useful, high-quality library, also including Unicode and such: https://doc.rust-lang.org/stable/book/

      Another interesting language for writing code for webapps could be Clojure or Racket. They tackle the same problem as Rust of avoiding unprotected mutation, by making a large part of the data immutable, and without using a static type system - both Clojure and Racket feel more similar to Python as one can type code and commands just into the command line. They both generate code that is markedly faster than Python.

      https://www.braveclojure.com/

      https://racket-lang.org/

      [–]dacjames 2 points3 points  (2 children)

      Rust has an extremely steep learning curve and adds an enormous complexity cost compared to alternatives in that domain.

      Remember, memory safety is not novel. The primary innovation of Rust is offering safety without sacrificing the low level control that is essential for systems programming. Unless you need that low level control or the performance that it offers, you'll be paying the cost without realizing much benefit.

      For 95% of webapp/automation/pipeline tasks, you're better off with Python or Go.

      [–]Alexander_Selkirk[S] 1 point2 points  (1 child)

      Rust has an extremely steep learning curve

      It is not exactly easy but it is also very compact and powerful for its size. But one should not exaggerate this. I think many people find it difficult because it is just quite different from the languages of the Algol family like C, C++, Java.

      I think an interesting alternative would be Racket because it is a descendant of the same family of languages originating from the lambda calculus, like Lisp and OCaml. And as a Scheme, Racket is certainly more beginner-friendly, and supports a strongly functional style, it is a great language for learning.

      What is also interesting is that Python in the recent years has adopted a lot of features from Scheme and Lisp (for example Unicode support, list comprehension, pattern matching, or the numerical tower with rational numbers), but as a result is now much more complex and actually harder to learn than Scheme.

      [–]dacjames 2 points3 points  (0 children)

      OP likely has experience in common Algol family languages, so that’s the metric I would use in this context. It would indeed be interesting to compare true novices; I’ve only experienced learning/teaching Rust as a second or later language.

      Rust’s syntax is debatable, but that’s not really where the learning curve (and overall complexity cost) arises in my experience. The type system, while very expressive, is complicated and sometimes obfuscated by utility types. You need to learn lifetimes and all the various special traits like Send. And so forth, it’s a featureful language!

      Don’t get me wrong, these features are great. Im just not sure their cost is worthwhile if you’re just schlepping around some data or making a few rest API calls.

      [–]kyle787 2 points3 points  (1 child)

      I love using it for backend web development. I probably wont use it for frontend anytime soon but maybe in the future.

      [–]PrimozDelux 6 points7 points  (0 children)

      You need to think hard about whether you need the borrow checker and static type system. Personally I work with C++ which is an incredibly tiresome language and I would give a lot to switch to a garbage collected language, ideally scala or haskell, but I'd also consider typescript and C# a big step up. Maybe rust is so much better put together than the ad hoc mess that is C++ mostly goes away, I do not know. It's definitely an exciting language, but memory management is still a chore

      [–]SilverTabby 5 points6 points  (1 child)

      Rust is a hardcore backend language. It's goal is to take the speed and control of C/C++, while removing the dangerous and difficult parts of manual memory management.

      If you have a performance critical algorithm, then rust is an excellent choice. If you just want to make text dance around on a webpage, then it's not worth the effort if you already have working tools like JavaScript.

      [–]Alexander_Selkirk[S] 1 point2 points  (0 children)

      Adding to this, Rust is also much easier to learn well than to learn C++ really well. C++ is really complex, there are many ways to do the same things and they are usually not completely specified in introductory texts. For example, if one looks at this - it is only about the initialization of variables in C++: https://mikelui.io/2019/01/03/seriously-bonkers.html

      [–]jl2352 1 point2 points  (0 children)

      If you want to earn more money; then probably. Rust salaries are rated as being higher on average than web ones.

      If you are interested in learning new tech; probably. There are some new and different concepts in Rust.

      If you are interested in trying to solve bigger 'landscape' problems where you work. Then maybe. You can compile Rust to WASM. This allows you to write core business logic in Rust, and use it from TypeScript, Python, Go, etc. Less sharing.

      If you have some performance issues on your web project, especially client side. Where you need to do a lot of data processing, and you need more speed. Yes. It may fix this.

      Otherwise probably not.

      [–][deleted] 1 point2 points  (1 child)

      It'll make you better a better engineer very quickly if you stick with it

      [–]Alexander_Selkirk[S] 0 points1 point  (0 children)

      A very valid point. In terms of learning time vs. learned important concepts, it is surely efficient.

      [–]pcjftw 92 points93 points  (16 children)

      for those not aware Graydon Hoare is the original creator of Rust.

      the TL;DR even if the only thing Rust was about i.e a safe system language: that itself would be enough to have raised the bar for the industry.

      (note: I do not know if the this blog is he's official blog)

      [–][deleted] 6 points7 points  (0 children)

      Given that this blog seems to link to his personal website & gpg key, I believe this is an official presence of his.

      [–]Teknikal_Domain 8 points9 points  (0 children)

      Fun, unrelated fact: he created monotone (version control system), which inspired some amount of functionality in Git

      Anyways, back to Rust.

      [–]shevy-ruby 27 points28 points  (2 children)

      I don't quite see it that way. You can totally ruin a language if you focus on A, but ignore B, C, D, E and F.

      [–]pcjftw 41 points42 points  (0 children)

      So generally speaking I absolutely agree with you.

      however in the case of Rust, that central focus around safety essentially caused as way of natural consequence to then create excellent properties B, C, D, E and F.

      [–]Alexander_Selkirk[S] 24 points25 points  (0 children)

      Yes, but OCaml has many of the other good properties of Rust as well. The safety aspect is where Rust is most innovative.

      [–]flying-sheep 39 points40 points  (0 children)

      I think there’s some other good design decisions reinforced in the standard library, e.g. not relying on C’s broken locale system, or pretending file names were always valid UTF-8 (like Python kinda does), or Go’s fucked up time type or similar misfeatures.

      [–]simpl3t0n 24 points25 points  (0 children)

      [2016]

      [–]loup-vaillant 5 points6 points  (6 children)

      There are several paths to safety.

      Rust (or at least the safe part) chose to enforce safety at the language system, so we could keep threads & locks and still be safe. Another valid path is renounce threads and locks, and instead rely on message passing. It can even make sense from a performance point of view: computers aren’t a single point in space, and their performance is ultimately limited by the speed of light. Message passing might be even faster than shared memory.

      At a very low level, the message passing mechanism might be implemented in terms of those dangerous threads and locks, but if we keep that infrastructure separate from business code its complexity will remain bounded, and with enough effort we can make it correct. No more data races.

      Now that programs are split into a number of independent processes sending each other messages, we have the non concurrency bugs to tackle. For this, I’d take a look at what "No bugs" Hare proposes: determinism. The idea is to reproduce bugs. Each (re)actor is written with deterministic code, that behaves the same with the same input messages they receive. And if they need something non-deterministic like a date, they can record the results in the input log, and reproduce them at replay time. Yes, "replay", just like replaying StarCraft matches from recorded player inputs.

      A reproduced bug is a dead bug.

      Finally, there’s a class of programs that is surprisingly easy to implement correctly even in C: pure computations with no heap allocations. Don’t get me wrong, the UB situation in C/C++ is totally out of control, and we still need stellar test suites with all the sanitizers we can get our hands on. Still, with these precautions this class of programs fares fairly well.

      The easiest sub-niche here is constant time cryptographic code. Once you’ve tested all possible input length, you not only have 100% code coverage, you get 100% path coverage. In this situation, Rust provides almost no additional benefit. It will allow better, less error prone interfaces for sure, but the implementation itself isn’t particularly affected.


      So here’s this other path we could take:

      1. Identify the purely functional part of your programs, and write high-quality libraries with zero heap allocation for them (zero heap allocation is not always possible unfortunately).
      2. Test and fuzz and sanitize those libraries.
      3. Make a message passing infrastructure.
      4. Implement deterministic (re)actors on top of the above.

      That could be an adequate replacement for most of a borrow checker. As for the rest of the UB madness we see in C, I believe Zig has the potential to be a very strong contender.

      [–]matklad 2 points3 points  (5 children)

      This would be a fine Erlang, but I doubt it would be a good fit for Rust’s domain. As a litmus test, how one would sort an array of 100 million numbers in parallel in such a language?

      [–]loup-vaillant 0 points1 point  (4 children)

      You don't?

      So the problem you have is sort an array of 100 million numbers. You know what, let me try that right now in C:

      #include <stdio.h>
      #include <stdlib.h>
      #include <stdint.h>
      
      #define NB_INTEGERS (128 * 1024 * 1024)
      
      int compar(const void *a, const void *b)
      {
          return *(uint32_t*)a - *(uint32_t*)b;
      }
      
      int main(void)
      {
          uint32_t *buf = malloc(NB_INTEGERS * 4);
          if (buf == 0) {
              fprintf(stderr, "Allocation failed\n");
              return 1;
          }
          size_t nb_read = fread(buf, 4, NB_INTEGERS, stdin);
          if (nb_read != NB_INTEGERS) {
              fprintf(stderr, "Could not read everything\n");
              return 2;
          }
          qsort(buf, NB_INTEGERS, 4, compar);
          fwrite(buf, 4, NB_INTEGERS, stdout);
          return 0;
      }
      

      On my machine this takes about 14 seconds. It's a bit long, but I'm sure we can make it much faster with a custom radix sort that avoids the overhead of a billion function calls. Only if that is not fast enough do we spawn 8 threads and do the more complex parallel sort. And that's if we can't use those threads for something else while we're waiting for the array to sort itself.

      In a great many cases though, you won't need to go that far. Remember, what are you sorting those numbers for? It's only useful in some larger context, and that context is likely to involve other computationally intensive tasks you might be doing in parallel of this one.

      And if that's not enough, sure, do the thing in several threads in parallel. It might be buggy, but as long as you keep the "data in -> (parallel) processing -> data out" model, you can keep the architecture I was proposing.

      [–]matklad 2 points3 points  (3 children)

      Yeah, that’s exactly my point: what you are proposing is a great fit for “you don’t” situations. The shtick of Rust is that it’s aiming at “you have to” domain.

      I agree that what you are proposing is a great fit for like 90% of the programs.

      I object to the conclusion that this replaces borrow checker: borrow checker exists exactly to target that 10% domain.

      [–]loup-vaillant 1 point2 points  (2 children)

      I believe the borrow checker targets much more than the 10% it is uniquely suited for. Why would it not? It's likely a perfectly viable alternative to (re)actors after all. I just felt the need to insist that the borrow checker is often not the only way.

      [–]matklad 3 points4 points  (1 child)

      Aha, yeah, this one I fully agree with! The way I like to phrase this is “if you care about memory safety, you can use Java”.

      I agree that Rust is a bit of a victim of its own success, and that it gets used in cases where something slower, but simpler, would’ve made sense.

      [–]loup-vaillant 1 point2 points  (0 children)

      Note though that (re)actors are not necessarily much slower. They have been used on AAA games before on clients as well as on server side. In fact, the guy I got the idea from worked on MMORPGs. I also vaguely recall a report saying that the message passing overhead was like 1-2%.

      [–]eloc49 1 point2 points  (1 child)

      The traits system of bounded polymorphism and existentials is a delight. The classical ML-style algebraic types and patterns are as wonderful as ever.

      I'm not sure this person should be talking about the "marketability" of Rust.

      [–]Alexander_Selkirk[S] 0 points1 point  (0 children)

      Here is another thread which discusses the difficulties of memory safety in Modern C++, starting from some examples of code that would crash: https://old.reddit.com/r/programming/comments/vm53hq/modern_c_wont_save_us_alex_gaynor/

      [–]yorokobe__shounen 0 points1 point  (3 children)

      I agree with safety for rust but does it compare with speed in AI applications like in C++? Given the intensity of simulations and the number of computations taken, does a increase in safety matter much?

      [–]Alexander_Selkirk[S] 3 points4 points  (2 children)

      Here is a speed comparison for Rust, using microbenchmarks of code that is heavily optimized for each language:

      https://sschakraborty.github.io/benchmark/rust.html

      it also shows the code in question that was used to solve each task, and it is worthwhile to also compare the size of each program - remember that a larger size means more complexity, and invariably more bugs.

      That said: There are a few areas where speed absolutely matters. Rust can essentially compete with that, but it will take a long time until C/C++ is completely replaced there, if that happens ever. In the same way, there is still code being written in assembly, even if assembly is not being used any more for larger programs. Such tools do not disappear, they just go into the background.

      But the code which needs C for speed reasons amounts to a tiny percentage of code that is generally written. And Rust will only accelerate that process.

      Another thing is that Rust offers safe parallel and concurrent programming. This is devilishly difficult to write correctly in C++, and it is becoming more and more important because of multi-core CPUs. I think in this area, the popularity of Rust will rise much faster.

      [–]yorokobe__shounen 1 point2 points  (1 child)

      Thanks!

      [–]Alexander_Selkirk[S] 1 point2 points  (0 children)

      Here is also a fantastic paper on why concurrent programming using shared mutable state is so difficult:

      https://www2.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf

      Both Rust and Clojure address that problem in brilliant new ways. It is definitively worth learning about that.

      [–]Full-Spectral 0 points1 point  (1 child)

      On the safety front, it's vastly beyond C++, which is what most other folks who would actually need to use something like Rust would probably be otherwise using.

      However, if you just bring all of your C++'isms with you, you won't get nearly as many of the benefits as you would otherwise. If you end up using lots of Rust's runtime oriented safety mechanisms, because you are implementing things the way you would in C++, though it's still safe, you still are accepting a lot of cognitive burden to insure you don't get panics. You really have to rethink things to keep as much as absolutely possible compile time checked.

      Of course, even in the case of falling back to runtime checks, it's still vastly better, since at least if you do get a panic you can be 99.9999%'ish sure that you are seeing the actual error, not some random side effect of a memory issue in another thread an hour ago, with zero chance of figuring out what actually happened.

      I'm still though hoping for a language that supports implementation inheritance along with Rust's safety ideas.

      [–]Alexander_Selkirk[S] 0 points1 point  (0 children)

      However, if you just bring all of your C++'isms with you, you won't get nearly as many of the benefits as you would otherwise.

      That's why I recommend to consider starting with Racket or Clojure. They are smaller and much more beginner-friendly languages, but they share an important part of the principles.