Okay, this article is called my thoughts on Rust after starting my startup. So I am two, two and a half or so months into starting a startup. And for my startup, I have written about 45,000 lines of code with the help of AI. But to be fair, I learned that AI was more of a pain than it was worth. And so I’ve pretty much abandoned all but abandoned using it. Now I keep it pretty minimal and make it do the really stupid basic stuff so that it doesn’t screw up anything important. So although probably most of those lines are written by AI, it’s only because I have patterns on objects. I have about 130 different objects that I need to have the same pattern on and I have five or six patterns on each of them. So I designed everything and implemented it for a couple and then made AI do the copy paste the boring stuff. Anyway, the point is, I have really generated myself 45,000 lines of Rust code. This is after about 10 years in the industry, four years working as a software developer and six years working as a IT consultant, primarily in the space of OpenShift, Kubernetes. So this is what I have learned about Rust coming back to programming after this long. In college, I got pretty familiar with C++, I used Python a lot, I messed around with some other languages like the D language and Haskell. In my four years of industry, I mostly wrote Java, I learned JavaScript, TypeScript. In all of my personal projects up until that time, I was doing them in Rust, but I wasn’t writing that much code. As a consultant, I wrote all kinds of code for all kinds of things, but not really software development. And at the tail end of my journey, I was writing my side projects in the Go language, which I really did favor for its ease of setup and relative straightforwardness. And to be honest, it works really well with vibe coding. So I was able to do a bunch of side projects very easily in Go. But this isn’t about Go or any of those other languages, this is about Rust. I am essentially reintroducing myself to Rust, because I was doing Rust back in the day, and now I’m doing it again. My software development experience has pretty much come full circle. And I have some thoughts. I have read so much about people not liking Rust because of its pretty lacking ergonomics. And I get that. Rust can be a really hard language to read, it can be a really hard language to parse if you don’t understand what you’re reading. It’s kind of a mix of all languages. It’s an imperative language if you write it like C. It looks object-oriented. If you’re using the impl blocks, even though it’s not object-oriented, unless you’re using dynamic traits. So if you’re not using dynamic traits, technically everything’s functional. Or technically there’s no methods, there’s function calls. And then you can write true functional code by instead of modifying something, you just return a new thing. And you can really enforce functional code by not using the mutable keyword. And there’s all kinds of helpful wrappers around the built-in data structures. So the vector and iterables allow you to do really complicated things in a functional programming way or in a non-functional programming mutable way. And then when you do have dynamic traits, technically everything is function call tables underneath. But it doesn’t actually work out ergonomically to be any different. It just changes what the runtime looks like. If you’re not familiar with lifetimes and you start seeing lifetime sigils everywhere, that’s really confusing. And of course, when you first start writing Rust, it is classical to refer to the early days as fighting the borrow checker. But here’s why I think Rust is still worth it. And by the way, this has nothing to do with the Go language or any other language that Rust is compared to. This is just my thoughts on Rust right now. Rust doesn’t have to look so complicated. Lifetimes and the fact that there’s three string types and the fact that there’s so many different ways of doing stuff, you don’t have to use any of that. At the beginning, when you’re learning Rust, don’t bother with lifetimes. You do have to fight the borrow checker a little bit. But once you understand how it works, it’s really not that complicated. To be fair, that is a big hump. Once you get over that hump, Rust becomes relatively easy. If you don’t understand strings, that’s fine. Just use the string object, convert all of the ampersand strs into string, and you just learn that the str.toString does that. And if you need to pass your string to an ampersand str, it’s string.asStr. It’s pretty easy. But it’s not intuitive. You could go into really complicated data structures and try to learn how to do cyclic data structures and yada, yada, yada. But honestly, if you’re working with hundreds of thousands or millions of items, just do the vector. Vectors are perfect for that. They work like Python lists, so they are arrays underneath the hood, and they’re just dynamically allocatable. So if you put too many items in it, then it will reallocate the vector. But this is actually considered the most effective way to do it. Because it is technically an array, working on the vector is faster than if it were a linked list. And so it’s worth the allocation cost usually. And 99% of the time, probably 99.9% of the time, vectors are fine. You’ve got all of the nice iterators on them. They are complicated to learn. I would really, really like it if Rust had, like, an easy button for iterating. Like if it was just vector.map thing, and it just does what you expect a map to do. Or vector.foreach. And it just does what you expect it to do. And then you’ve got all of the other tools for the more complicated stuff. It is for sure complicated when you have to do vector.iter.enumerable.map.collect with the turbo fish. It does look ugly. But you can start with the easy stuff in Rust. And really, it is easy. And you don’t even have to do any of the iterable stuff. You can write Rust like C. You just for loops. If you get clippy involved, it will teach you slowly how to do the more Rust-like way. But you can ignore that. You can do C-like code in Rust, and it will work exactly the way you expect. You can have structures. You can have functions. And you can call those functions with structures passed to them. All you have to do is understand how the borrow checker works. And it’s easy. Basically, Rust is C, but safe. But also, if you want to go one level higher and use implementation blocks, a struct with an implementation block with each function taking as its first argument a reference to either itself or a mutable self, which is all just sugary which is all just sugar syntax on top of writing a function which the first argument is the object that you’re working on. But now you get to write object.method. But it’s still a function. There’s no method call. It’s not redirecting behind the scenes. There’s no function call table. Unless you explicitly set that with some more complicated syntax, like taking in an ampersand dynamic object. Or using one of the smart pointers, like box. Then you’re technically doing methods. But the syntax looks the same. You can slowly work up your Rust knowledge into the more complicated things. You don’t need to jump into the deep end all at once. I already jumped into the deep end before. So I kind of just jumped into the deep end again. But I had to just remind myself of all those things. If you’re learning these things for the first time, I’m trying to remember being back in college and learning this for the first time. It was complicated. This is not easy. I still believe to this day, I believe back then and to this day, that learning Rust will make you a better programmer in any other language. Just like I believe that learning C++ will make you a better programmer in other languages, too. C as well. I just never really learned C. So I don’t have that personal experience. When I remember back to my college days, learning C++, and I did all of those hard things, and I learned how I eventually learned how C does memory allocation, and how C++ does that behind the scenes, and how constructors and destructors work. When I learned Java, that was easy. All of a sudden, Java was just C++, but easy. I didn’t have to think about constructors and destructors. I didn’t have to think about memory management. I didn’t have to think about smart pointers. I didn’t have to think about pointers. C++ now has smart pointers, but back then, I was using C++ 97, which didn’t. So I didn’t have smart pointers. I didn’t have any of those high-level stuff. I was doing everything raw. One of the most complicated things I did in C++ was operator overloading, which was pretty cool. I really liked it. But the point is that if you learn C++ first, Java is easy. There’s really no… It’s truly the right way to go about it. Learn an easy language first, like Python, but then learn a really hard language. If you’re going to stick with programming for a really long time, learn a hard language, and then everything else becomes easier, but also, you understand what everything else is doing. And Rust is one of those languages where after learning C, C++, and Rust, you have effectively the most thorough understanding of what a computer is doing, what a language does behind the scenes when you do Python high-level work or Ruby high-level work. In fact, I think that Rust is probably… Because you can write Rust in a simple way, yes, it’s still a little bit complicated, but because you can write Rust in a simple way, I actually would recommend it over a lot of other languages that people would usually use because they think Rust is too complicated. And one of the other reasons for this is that Rust is fast by default. It is a very fast language by default. So even if you do kind of slow operations, you’re still beating most of the other languages. So even if you write naive Rust, you’re probably going to be faster than Python, Ruby, or Java. And even Java isn’t a slow language. The way Java programmers write Java tends to be slow, putting way too much indirection and high-level classes and inheritance. Making Java very complicated and very hard to read. Very hard to track down what’s going on. So in this section, let’s compare Rust to some other languages. Python. Python is a great language if you just want to do something simple. If it’s not a complicated system, if there isn’t a ton of lines of code, if you don’t really need types. I mean, that’s why it’s used for machine learning is because even though Python is a slow language, all of those machine learning libraries are written in C. So you can make Python fast, you just write it in C. It’s kind of a cheat, but it’s actually a very convenient cheat. But even then, Python, typeless, it’s got some issues. Which means, you know, Rust would be good if you have relatively simple code. Rust is still easier to use. No, Rust is not easier to use. If you have relatively simple code, Rust is easy to use. Python might be easier, but if you had any inclination of avoiding Python’s speed problems, Rust is going to beat it every time. Ruby is Python, high-level, but I believe with more types and some more sort of fundamental programming principles. But if you write in Ruby, that probably means you’re using Ruby on Rails, and that means you have to listen to DHH’s bullshit every fucking month he comes out with something, some new hot take. So you probably don’t want to write in Ruby. If you’re writing in C, you probably already know what you’re doing, and you don’t need to read this list. There’s probably a good reason that you’re writing in C. On the other hand, if you’re willing to brave, basically, the borrow checker, you can write C but better in Rust. C++ is, among other things, just a horribly complicated language. If you need C++, you’re probably doing AAA video games or some sort of video game system. You’re probably building video games if you’re writing C++ today. It’s not used for servers anymore, that’s for sure. Even so, I think that Rust is still better. C++ has high-level concepts, but it’s a low-level language. Rust has high-level concepts, but it’s a low-level language. Neither of them have a garbage collector, but Rust can keep most of the errors out of the system that C++ will consistently run into. Now, C++ might be getting an optional borrow checker because C++ is the every language and it just absorbs all the features of other languages. That is fine. It makes the language complicated, but it does, in fact, mean that you can get some of those benefits. With Java, you don’t choose to use Java. Your company chooses Java for you. If you’re choosing to use Java as a side project, it’s probably because your company makes you use Java and that’s just what you’re used to. Nobody’s comparing Java to Rust. Unless you’re in the very, very specific subfield of server maintenance, like building servers outside of a corporation, because a corporation will always make you use Java just because they’re locked into it. That’s just what they do. But if you were trying to choose a good server, Java isn’t bad at that. You just have to write Java in a sane way. But the fastest frameworks are all written in Rust or Go. I think Java has fast frameworks, but they’re not very popular. The fact of the matter is that if you’re writing a modern server today, there’s really no reason you shouldn’t choose either Go or Rust. There’s really no reason to choose Java. There’s still a handful of other languages out there that are purpose built. If you’re writing websites, you’re going to use JavaScript. That’s just all there is to it. You should probably use less JavaScript. You should probably do frameworkless HTML, CSS, and JavaScript. CSS has come a long ways. HTML5 has so many extra features. The vast majority of what people use React for is unnecessary. When you do need a really, really complicated thing, then React might be your thing. But between JavaScript, CSS, and HTML5 getting good features, and with application frameworks written in C, C++, and Rust being able to be run in WebAssembly on the web as full applications, I do not think that there’s a reason for React to exist anymore. But it will take time for it to phase out. The better applications, the best web-based applications will be written in Wasm. Something that compiles to Wasm. Regular websites will always be better as HTML, CSS, and JavaScript. Even complicated websites can use those raw tooling. But if you really, really, really need super complicated stuff, Wasm is going to eventually I believe that Wasm will crush JavaScript frameworks. And if it doesn’t, it will be sad. Because the Wasm frameworks are better. And they have options outside of JavaScript. There’s a handful of mathy languages. There’s a handful of purpose-built languages. And those will always be what those are for. The Go language I think is a pretty good language. It’s got a few problems. There’s definitely some ergonomic issues. There’s some very questionable decisions. But it’s really a fairly small problem. Go is a pretty easy language to learn. It’s a pretty easy language to write. It’s a pretty easy language to read, minus all of the if-error fluff. Go is a fantastic language for most use cases, really. Simple and less complicated and it’s still typed at least. It’s really good. But if you just need to squeeze every bit of… If you need to start at fast performance, and you can work your way up to something like complexity and deeper performance improvements and optimization, Rust is the language that just kind of spans the entire spectrum. I repeat myself, but you can write Rust similar to C, just with the borrow checker, essentially making C-like code safer. You can get a lot of, if not all of, the high level concepts out of C++. You can build servers that are way more efficient in Rust compared to Java. You can even write front ends that are compiled to Wasm, so JavaScript doesn’t need to exist so long as people are willing to use Wasm apps. And last but not least, I think the only other language that is really in competition for long-term use is the Go language. I think that Go is great at a bunch of stuff that Rust isn’t good at, and Rust is good at stuff that Go isn’t good at. And in fact, all of these languages still have their place. I’m not saying we should stop using any of them. It’s just that I have learned as my reintroduction to Rust that comparing it to all other languages, Rust makes the most sense for so many use cases. Not just to be a Rust evangelist, either, because that can be really annoying. One of the reasons that I still think that Go is a useful language is because Rust is more time-consuming to write. There’s no doubt about it. You can write Go faster than Rust. And Go has this fairly complete standard library such that if you write if you want to write if you don’t want to bring in a library and you want to interface with web APIs and build servers and do command line stuff, you don’t need to go outside of the standard library to do it, and everything’s pretty straightforward. And it’s basically not changed. It’s pretty much the same as, you know, early days of Go. Which is one of the reasons that language models are pretty good at writing it. Rust has some Rustisms that have changed over time. Truly, at the end of the day, I like both of those languages a lot. I just think that Rust, in my experience now, Rust has taught me that you can use it in easy ways. You can use it in more complicated ways. You can use it in naive ways. You can use it in performance-critical ways. You can use libraries that do all the work for you. It’s a little bit more verbose if you want to build stuff yourself. I just feel like Rust, to me, is a good broad, very broad use language.
[Read More]