15 ms·
Great things about Rust that aren't just performance
- mhsdef 2y agoNails it. I'm so tired fighting incidental complexity--our tools. Speed is great but let me just focus on the business problems and write something durable.
- slekker 2y agoThe "billion dollar mistake" in Go is a non-issue: there's no security consequences (it panics safely) and it is the easiest kind of error to fix, it tells you exactly where the null pointer is.
- VBprogrammer 2y agoWhich is great if you are the exact person, team, and organisation which wrote the code and / or has access to the source code as well as the time and knowledge to know-how to fix it.
- hansvm 2y agoThere's nothing I like more in the middle of the night than being paged about some skiddie making the webserver repeatedly panic ... safely. Surely you recognize the benefit in that sort of thing being pushed to a compiler error?
- continuational 2y agoNull pointer panics rarely happen where the null is introduced. Instead the null propagates somewhere else where you assume non-null, and you get the panic there. That's bad error reporting, and it only happens because Go lacks a proper nullable/option type.
- kolektiv 2y agoI'd agree with that if I hadn't had commercial products written in Go crash in production. They're the kind of errors that slip through the net, and "it's easy to fix" is shall comfort at 2am staring at a downstream 500 error.
- kbolino 2y agoThe problem with nil in Go is that there's no ergonomic way to deal with it. Neither the language nor the type system are amenable to anything better. The lack of the ternary operator or any other conditional value expressions means that handling nil properly always adds at least three lines of code for every dot in an expression. Even generics don't help much because "nil" is actually 5 different things (nil pointer, nil slice, nil map, nil channel, nil interface) none of which are interchangeable. And strings can't be nil, which probably seemed like a cool idea at first but now just means you see *string all over APIs even though string is a fat pointer under the hood.
- lordnacho 2y agoFor me, there's a headline draw, which is the borrow checker. Really great. But apart from that, Rust is basically a bag of sensible choices. Big and small stuff: - Match needs to be exhaustive. When you add something to the enum you were matching, it chokes. This is good. - Move by default. If you came from c++, I think this makes a lot of sense. If you have a new language, don't bring the baggage. - Easy way to use libraries. For now it hasn't splintered into several ways to build yet, I think most people still use cargo. But cargo also seems to work nicely, and it means you don't spend a couple of days learning cmake. - Better error handling. There's a few large firms that don't use exceptions in c++. New language with no legacy? Use the Ok/Error/Some/None thing. - Immutable by default. It's better to have everything locked down and have to explicitly allow mutation than just have everything mutable. You pay every time you forget to write mut, but that's pretty minor. - Testing is part of the code, doesn't seem tacked on like it does in c++.
- jvanderbot 2y agoAdd to this: trait system vs deep OOP. Really nice macro system. First class serde. First class sync/send Derives!
- pjmlp 2y ago"Applying Traits to the Smalltalk Collection Classes", 2003 https://rmod-files.lille.inria.fr/Team/Texts/Papers/Blac03a-OOSPLA03-TraitsHierarchy.pdf https://rmod-files.lille.inria.fr/Team/Texts/Papers/Blac03a-... Traits as CS concept, are part of OOP paradigm.
- jvanderbot 2y agoThere are shades of OOP, and while you're technically correct I think the meaning of my post is clear.
- sshine 2y agoTraits as CS concept, are part of FP paradigm. Reverse Uno!
- ninkendo 2y ago> I can express a lot in Python, but I don't trust the code as much without robust tests. This is a major part of why I like languages like rust. I can do some pretty fearless refactoring that looks something like: - Oh hey, there’s a string in this struct but I really need an enum of 3 possible values. Lemme just make that enum and change the field. - Cargo tells me it broke call sites in these 5 places. This is now my todo list. - At each of the 5 places, figure out what the appropriate value is for the enum and send that instead of the string. - Oh, one of those places needs more context to know what to send, so I’ll add another parameter to the function params - That broke 3 other places. That’s now my to-do list. Repeat until it compiles, and 99.9% of the time you’re done. With non-statically-typed languages you’re on your own trying to find the todo list above. If you have 100% test coverage you may be okay but even then it may miss edge cases that the type checker gets right away. Oh and even then, it’s likely that your 100% test coverage is spent writing a ton of useless tests that a type checker would give you automatically. As nice as weakly/dynamically typed languages are to prototype greenfield code in, they lose very quickly once you have to maintain/refactor.
- Cyph0n 2y agoAnd if say one of your enum variants expects a string reference (pointer), the borrow checker will guide you through ensuring that the reference you pass in is valid at all callsites. Importantly, no tests are required to guarantee that the refactor is safe - although no guarantees that it’s logically correct. On the other hand, doing this exercise in a different low-level language involves a lot more “thinking” instead of just following the compiler’s complaints :)
- Aeolos 2y agoWith rust, I treat compiler errors as ultra-fast unit tests. I share the same experience: once it compiles, 99.9% it works fine on first try. It's a wonderful development experience.
- lblume 2y agoI completely agree, if it is really 100% Rust, or some great high-level bindings. Else it just becomes C++ with nicer syntax imo, and if my code isn't anything too fancy I could just write it in Python which likely has even more ergonomic bindings. In my free time I code 90+% in Rust, but for some areas, like OR (SAT, MILP, CSP), ML or CAS Python seems to be the better choice because types don't matter too much and if your code works, it works.
- jtwaleson 2y agoI really enjoy Rust so far. I've been writing a relatively simple web app on Loco.rs with it, backed by a very fast multi-threaded git history parser. It's super fast and safe and catches most problems with compilation checks. My two main problems now are 1) that AI code assistants (Claude 3.5 Sonnet) + IDE support (VS Code / Cursor AI) are still much worse than with frontend frameworks like React/VueJS. The AI suggestions are mostly terrible. 2) Compilation is really really slow. There is no hot reload, and it often takes about 1 or 2 minutes for my new code to be live in my dev server. It's a real flow-state killer. It's a bit ironic as all the Python/Javascript frameworks are now super fast because they've been rebuilt on Rust.
- the__alchemist 2y agoThe pros/cons of rust add up better than other languages. The people who I hear (recently: Jon Blow) throw spears are usually correct, but what they're missing is that you could throw pointier ones at the alternatives. Some examples: - Best mutability ergonomics of any language. E.g. `&mut` in a function parameter means the funciton can mutate it; `&` means it can't. This might be my favorite part of rust, despite sounding obvious. Few languages have equivalents. (C++ and D are exceptions). - Easy building and dependency management - No header files - Best error messages of any language (This is addressed explicitly in the article) - Struct + Enums together are a fantastic baseline for refactorable, self-consistent code. - As fast as any - Great overall syntax tradeoffs. There are things I don't like (e.g. Having to manually put Clone, Copy, and PartialEq on each simple enum, and having to manually write `Default` if I need a custom impl on one field), but it overall is better than alternatives. Rust enthusiasts online are often unpleasant, and it's perhaps their fault people are put off by the language. They repeat things like "fearless concurrency" "if it compiles, it works", and "that code is unsafe/unsound" without critically thinking. Or, they overstate rust as a memory-safety one-trick, while ignoring the overall language advantages. Tangent: Async rust is not my cup of tea for ergonomics and compatibility reasons. I have reason to believe that many people who like it think Async is synonymous with concurrent processes and nonblocking code.
- iknowstuff 2y agoI like async rust because its an engineering marvel. There are other ways to do it, but they are all worse, slower, and less versatile: https://embassy.dev/ https://embassy.dev/ https://without.boats/blog/why-async-rust/ https://without.boats/blog/why-async-rust/
- the__alchemist 2y agoI do lots of embedded; not an Embassy fan for the classic Async reasons. Disagree on being worse, slower, and less versatile. That is wrong on slower; the other two traits are subjective. The embassy creator is a great programmer, and we see eye-to-eye on typestates and HAL unification, but not async.
- 2y ago
- isodev 2y agoWholeheartedly agree. One can just be at ease that the compiler has it covered and one can focus on coding. Both the tooling and the syntax for these protections is kind of “out of the way” as well - I don’t have to learn extra keywords just to convince the compiler that what I’m doing is “safe”, it can do that by itself.
- pryelluw 2y agoI’ve been focusing more and more on rust for my personal projects and I agree with all of these. What im waiting for is the Django equivalent in rust. Dunno if its already here but I’m hoping. The one thing I do enjoy in rust is how you don’t need an excessive amount of tests to ensure it runs fairly correctly. I’ve spend more time writing tests in the last ten years using Python/js than writing actual code. Such a waste of productivity.
- ku1ik 2y agoI would argue web dev is just not Rust’s sweet spot, and I wouldn’t hold my breath for „Django for Rust”.
- pryelluw 2y agoThat’s what people said about Python before Django. They asked why not use PHP or Perl. But Django came along and established a strong set of patterns that make web dev much easier these days.
- vkazanov 2y agoAs somebody who wrote maybe half a million lines of python code, I still must say that it is Rails that became a model. Django was (is?) the default tool for python, but i don't remember it being discussed as widely.
- pryelluw 2y agoYes, rails definitely in a bigger scale. Django within pythons ecosystem. IME fastapi has eroded some of Django’s hold but it’s still chugging along nicely. Hype has certainly died down because it is ancient by today’s standards. Still a very good tool and quite a lot of work available around it.
- the__alchemist 2y agoConcur. I don't do web backends in rust for this reason. There are some good Flask analogs though.
- sesm 2y agoI'll swallow the bait and try asking some sceptical questions here. My understanding of Rust memory management is that move semantics and default lifetime-checked pointers are used for single threaded code, but for multi-threaded code Rust uses smart pointers like C++, roughly Arc = shared_ptr, Weak = weak_ptr, Box = unique_ptr. My question is: what extra static checks Arc has over shared_ptr? Same for Weak over weak_ptr, and Box over unique_ptr.
- calo_star 2y ago> but for multi-threaded code Rust uses smart pointers like C++ That's not the whole story. There's also Send and Sync marker traits, move by default semantic also makes RAII constructs like Mutex<T> less error prone to use.
- CJefferson 2y agoIn rust, you still can’t get mutable access to any object in two threads at the same time in a non-thread safe way. In “very rough c++ish”, stuff in a shared ptr is immutable unless it is also protected by a mutex.
- sesm 2y agoOk, so do I understand correctly that Arc<MyType> would be read-only, and for write access I'll have to use Arc<Mutex<MyType>> or Arc<RwLock<MyType>>? So what about Mutex and RwLock, do they have any static checks associated with them? Do they introduce an extra layer of pointer indirection, or Rust resolves Arc<Mutex> and Arc<RwLock> to 2 different implementations with only 1 layer of indirection?
- meltyness 2y agoDefinitely will take the Pepsi challenge on 'go doc' with 'cargo doc'. Go doc had a bunch of, puzzling things going on / barely working, Rust doc is pretty much as described in the book and reference. Although in the C ecosystem, Doxygen is pretty nice, the docs there have to be 3d to account for the way C code bases can work.
- xvfLJfx9 2y agoFor me it is the excellent tooling. Great package management, good compiler errors, automatic formatting and enforcing if guidelines etc.
- jurgenkesker 2y agoI enjoy Rust, but have settled on Kotlin for my language of joy. I use it in my day job for Android, but also recently started converting personal project backends and APIs to it (mainly from Ruby). I really like the ease and joy Kotlin gives me, and if I need a very high performance or very low level project/library, I'll write it in Rust. Rust is too slow for me (when coding), so a bit too low level I guess. In Kotlin I can express everything I want.
- 8s2ngy 2y agoTwo things concern me about Kotlin: 1. The language and its future are heavily intertwined with JetBrains and their motivations. It's difficult to say whether this is a good thing or bad, but issues like the one discussed at https://discuss.kotlinlang.org/t/any-plan-for-supporting-language-server-protocol/2471 https://discuss.kotlinlang.org/t/any-plan-for-supporting-lan... don't inspire confidence. 2. Java seems to be moving ahead at a rapid pace and is slowly absorbing many of the features that once distinguished Kotlin. This makes it difficult to jusify introducin Kotlin at a company where Java is heavily used.
- akkad33 2y agoWhat feature do you use Kotlin for that does not exist in modern Java (21+)?
- lblume 2y agoComplete by-default null safety is a big point, extension functions are just nice, smart casts, proper data classes and operator overloading, and simple expressive functional stuff like range syntax and reified generic types for inline functions. In general the Kotlin language feels more usable, yet less bloated (wrt the actual code, not the features ofc).
- akkad33 2y agoThose are actually very good features. I guess null safety will come to Java with project Valhalla.
- 8s2ngy 2y agoEven though I am not as proficient with Rust as I am with the languages I use at work, it has quickly become my favorite language as I dive deeper into it. It has helped me connect many dots that were fuzzy in my mind, like static typing, enums, pattern matching, traits, compile-time safety checks, and so on. A fair argument can be made that these are not unique to Rust, but it presents them in a cohesive package that I have not seen in any other language. Add to that its well-integrated build system and the enthusiastic community of developers who are passionate about it, and its appeal is undeniable. The lessons I gain from Rust directly translate into a better way of reasoning about code written in other languages.
- dmezzetti 2y agoRust is a fine language and good for certain use cases. There is a segment of developers where the syntax and complexity is a bridge too far. The community tends to evangelize the greatness of Rust too much and be unrealistic with this reality.
- tpoacher 2y agoMeanwhile, bryan lunduke blogged this today: https://lunduke.substack.com/p/massive-memory-leaks-in-system76s https://lunduke.substack.com/p/massive-memory-leaks-in-syste...
- demurgos 2y agoI haven't finished listening yet; but it should be made clear that Rust claimed to prevent double frees and use-after-free errors but never claimed to prevent memory leaks. Memory leaks were actually decided to be fully safe just before Rust 1.0, and there are multiple safe methods to leak memory. Search for "leakpocalypse" if you want more details. I also spent the day fixing a memory leak in an Angular (JS) project: you can create memory leaks in almost any language, including memory-safe ones (even garbage-collected ones). The tone of the podcast seems needlessly incendiary. EDIT: He actually quotes a part of the doc were they say that "memory leaks are hard but still possible". It's disappointing that Cosmic has leaks; but it's more about Cosmic than the language IMO.
- lblume 2y agoYou can't really accidentally cause memory leaks without being made aware that your code may leak by the compiler and/or docs. The "easiest" way to do it accidentally would be an Rc loop, but that is harder to write than Rc::new_cyclic which gives you the memory-correct Weak reference. When you stick to a fully owned tree memory model (or use bump allocators for fancier data structures) things usually turn out very easy, and I pretty much never had to worry about this.
- demurgos 2y ago> You can't really accidentally cause memory leaks without being made aware that your code may leak by the compiler and/or docs. It's true if you stick to the standard library, but I assume that the Cosmic frameworks adds a layer of complexity. I'm not familiar with their codebase, but I can easily see how an Rc cycle can appear behind a system with lots of shared references (e.g. callbacks, GUI components with backlinks, etc.). You can also get memory leaks through caches without a clear eviction policy. You can also get cases of "memory amplification" where you hold an Rc to a larger struct despite only needing a tiny amount of data from it. Basically, I agree that the standard library tries to steer you away from memory leaks. However, I also understand that it's not foolproof and can see how you can get in a situation with leaks when your approach is to take some tech debt to avoid short-term delays.
- IX-103 2y agoOne thing I don't like about Rust is implicit function return. Flow control should always be explicit. Given the other choices made in Rust to make flow control explicit (such as the absence of exceptions), I was surprised to find this choice. Fortunately the "return" keyword is allowed so I include it in my code to make it explicit. I just have to remember to look for it in any other code I'm reviewing.
- tonyedgecombe 2y agoI don't think match would work so well if blocks weren't expressions.
- joshfee 2y agoReturning control to the caller only really needs to be explicit if you're doing it in an arbitrary spot in the middle of the function because if you're at the end there's nothing to do _other than_ return control. For instance in other languages you don't need to explicitly say "go to the next iteration" at the end of a for loop, and if you want to do it before the end of the loop body you can `continue`. If "flow control should always be explicit", then should we be writing `continue` at the end of our loop blocks? I think the other part of it is that it is just part of a cohesive language design where everything is an expression, including things like if's, matches, etc that would be control flow statements in other languages.. It would be a little weird to say that functions are the only thing that have different semantics.
- ausbah 2y agowithout even reading the article hands down the expressiveness of algebraic data types and pattern matching it enables is my absolute favorite part of rust
- threeseed 2y agoSurprised more people don't talk about panics and third party libraries. So a panic is when something happens that shouldn't and you want the app to just die. But the problem is that third party libraries can do this as well. And there is no way to wrap this behaviour. For example, I used a PDF library that would panic when the file was doing something not in the spec. And rather than me being able to put up a dialog that said "this PDF is invalid" my entire process would die. Not great for a desktop app. It is one of the more insane situations I've ever seen in programming in 30+ years. You literally have to beg third party developers to consider what is best for you rather than them.
- Lorak_ 2y agoI agree that libraries should avoid panicking, but it is not true you can't do anything about it. You can wrap a call to such library into https://doc.rust-lang.org/std/panic/fn.catch_unwind.html https://doc.rust-lang.org/std/panic/fn.catch_unwind.html
- prmph 2y ago> This function might not catch all Rust panics. A Rust panic is not always implemented via unwinding, but can be implemented by aborting the process as well. This function only catches unwinding panics, not those that abort the process.
- Lorak_ 2y agoAs far as I know panics abort instead of unwinding in three cases: - When a panic happens during panic unwinding - When the application (not the dependency!) sets panics to abort in Cargo.toml - When the target doesn't support unwinding. Which of those is the case for the desktop app described by the parent?
- threeseed 2y agoDid you read the part about types needing to support UnwindSafe. I typically don’t control every type that I am interacting with.
- Devasta 2y agoFor me, the amazing error messages are what makes it great. I am not a professional dev, but I regularly contribute to an open source project because of them. I would never consider sending PRs in another language, how would I know If I am wasting the projects time by contributing bad code? With rust though, I have clippy and the compiler helping me along the way, like pair programming, I can be fairly confident I'm sending something useful.
- adityajha36 2y agoComing from a Python background, working with data heavy analytics in finance, one of my biggest Rust-is-the-one moment has been because of Polars. It lets me do everything I could do with Pandas, but with added speed and safety. Lack of such packages (as far as I'm aware) in Java, C++ and other languages keeps an entire ecosystem of data-heavy workloads in Python. But most Python projects I've found are very hard to scale beyond the prototyping phases.
- EddieRingle 2y agoAre you familiar with Kotlin's DataFrame? (https://github.com/Kotlin/dataframe https://github.com/Kotlin/dataframe) JetBrains also keeps a list of other data analysis libraries for Kotlin (and Java) as well: https://kotlinlang.org/docs/data-analysis-libraries.html https://kotlinlang.org/docs/data-analysis-libraries.html