people_who_want_to_keep_using_the_language / people_who_have_used_it_in_the_past_year
Since Rust is so early in its adoption and there are few jobs, many of the responders are hobbyists who are into Rust, like it and want to keep using; not necessarily people who use it for work. And since you only take into account the people who have used it in the past year, you ignore all the people who have tried Rust before that and didn't like it.As an extreme example, let's say I created a language in 2020, the entire software community tried it and they absolutely hated it and unanimously rejected it as the worst language ever but it still has 2 users (my mom and I) who want to keep using it - that languages would score 100% Most Loved on stackoverflow's survey even though it was hated by the overwhelming majority of people who tried it.
With this formulation you create the strange effect that if people hate a language enough to stop using it, the language's most loved metric goes up after a year.
For most people who program for a living, the hype over Rust means little. They need to use what is in the industry right now. Often, that is a tried and true language that is relatively easy to learn and use.
Having a complex programming language which limits you and controls how you use it does not sound appealing to those who need a feature done, fast.
This is so interesting to me. I'm a Rust programmer by trade (as in - I'm not a hobbyist, I actually write Rust for work). We've found that, while the feature work is a bit slower in Rust than in other languages the company used to use (mostly Python), they tend to require a lot less maintenance down the line (less bugs, easier refactoring), and so it ends up canceling out a bit.
I also never find that Rust limits or controls me in my day to day work. There are some things you cannot do easily, sure, but those things tend to not matter in application code. Linked lists are hard, graphs are hard, but when writing an app, I just use an existing dependency like petgraph or std::collections::LinkedList instead of reimplementing those datastructures. And if you need to write those things, it's not like it's impossible, you just need to drop down to unsafe rust, and ideally figure out some safe way to expose that API.
Really, the biggest disadvantage of Rust is that its learning curve makes onboarding newcomers much harder if they don't have experience in the language. For Python/Go/JS/Ruby you don't really have this problem, even if a potential recruit doesn't have experience in the language, they will probably be able to pick it up as they go without too much trouble. But in Rust, it can take a fairly significant amount of time to get up to speed and stop fighting the compiler, in the order of several months.
A lot of programs written in Rust would almost certainly be better off being written in Kotlin. The one in the article is a good example. Why are they writing a messenger bot in Rust? That doesn't seem like the sort of use case Rust was targeted at. It's also a modern language with a lightweight syntax and pretty good static typing, great refactoring tools etc, but it's way more user friendly. There's no borrow checker because it's GCd, compile times are much faster (at least for the JVM version) etc.
You can also use Kotlin/Native or GraalVM native-image to produce standalone executables that don't need a full JVM, if that's a requirement for your use cases. The native images are astounding. They can start faster than programs written in C and their memory usage is also way less than a typical JVM app. Downside is of course compilation time but you can avoid that by just developing on the normal JVM and then AOT compiling at the end when it's time to release.
AFAICT Rust is a general purpose programming language. People can use it how they want. How do you learn a recent programming language? "hey boss I'm going to write production code in a new language that I haven't learned. Lol YOLO"
Now if we were talking about some other "new languages" not naming names, you can memory leak kilobytes writing hello world... Yikes.
Dynamic languages and GC'd languages cover most of what our employers are paying us for: web apps, backend services. It is ironic to build super safe software, then deploying them on kubernetes, written in a GC'd language prone to nil dereference errors.
Rust has its place, but it's a very small place. These days computers are so fast there's companies worth billions built on Ruby and Python, if you go native with a GC language you'll cover 98% of your needs.
Rust IMHO has gone too far towards safety at the expense of developer ergonomics and pragmatism. We're so expensive that adopting a subpar language that is easier to grok is often a savvier business decision.
Indeed. I'm a Rust dev somewhere it actually matters (video dev - we have to process 60 frames a second, for hours/days on end, with completely predictable performance, without crashing once) and I'd never pick it if I just wanted to build a webapp where nothing really matters and if the whole thing falls over we can just put it in a retry loop.
There's plenty of code out there that /cannot/ be written in Ruby/Python/Go/C#. Rust solves some really hard problems for people working on that type of code. But it's not what most people on HN are working on.
I think the problem is that a lot of web developers do not really understand that this type of code exists, and that languages which do not target web development can be exciting.
But without even going as far as frontend web applications, stuff like backend services, system services, GUI applications, CLI applications, etc., don't actually need all that much memory safety and control over allocations.
My understanding is that Rust was designed to be a safe(er) language to write low-level system code than C/C++, not to compete with Python/Ruby/Java for web development applications.
I'm complaining about everybody on programming forums, including HN, seeing Rust as the replacement for most, if not all languages. My opinion is that Rust's ideal problem space is much narrower than people think.
>It is ironic to build super safe software, then deploying them on kubernetes, written in a GC'd language prone to nil dereference errors.
Nil dereference errors don't demonstrate an absence of memory safety. If the runtime checks for a nil reference before dereferencing and then raises an exception, that's perfectly safe.
I don't think the null handling in rust is about memory safety so much as it is their choice in error handling. If you come across a null pointer dereference and your code doesn't handle it, that's a hidden bug. Triggering an exception and handling it is a valid approach, but there are trade-offs. If no code handles the nil exception for example then it's no better than crashing as you would in C. Wrapping things up in try catch can lead to missing recoverable errors or unexpected states. The choice to disallow null is one to avoid common bugs, not one for memory safety, as far as I understand it.
> One common example is modifying a vector element by reference. If you grab a reference to an item, push something else to the vector, then try to access through that reference, the vector may have re allocated during the push and you're either no longer looking at valid memory because it's been freed, or you're looking at a stale copy of the element.
There aren't that many languages which both use GC and allow you to take references to elements of a vector. Go would be one example. I can assure you that you cannot access undefined memory regions by doing this in Go. (What would happen is that the original allocation backing the vector would be retained in addition to the new allocation.)
>If no code handles the nil exception for example then it's no better than crashing as you would in C
C programs are not guaranteed to crash when a pointer has an invalid value. Dereferencing a NULL pointer will reliably cause a crash if you're running the code on top of a modern general purpose operating system with memory protection, but invalid pointers (which don't necessarily have to be NULL) have the potential to access arbitrary memory regions without raising any kind of error.
Current implementation of slices and interfaces in Go is not memory safe in presence of data races:
https://blog.stalkr.net/2022/01/universal-go-exploit-using-d...
Nope, unsafe isn't a way to do dependent typing in Rust.
This is something that escapes a lot of people nowadays.
Everyone uses a browser and they are inherently unsafe.
Meaning that Firefox's gains with Rust will eventually be lost given its market adoption is slowing reaching zero.
https://docs.google.com/document/d/e/2PACX-1vRZr-HJcYmf2Y76D...
https://www.chromium.org/Home/chromium-security/memory-safet...
But yes you are right, anytime you have two or more accesses to a data structure you do have to think a little harder about it. Usually you just want to use a reference to that object, sometimes it makes sense to clone it, sometimes you want to pass it by value and return it by value. In the case of doubly linked lists you probably want to drop into unsafe code.
I get it though, GC languages are more zen in that regard.
Libraries are typically optimized for generic use, so are often more complex, slow, and difficult to extend with new features (both coding wise or the features might not be suitable / have trade offs for other people).
Yes making data structures is important, and the reality of that is, there are people in the ecosystem creating fancy ones which can be leveraged for your use case.
If that doesn't exist then yea you have to write them. Sometimes that's difficult(you need to use unsafe), sometimes it's easyish and you can use all safe(I did this for a graph type). It can be done(lots of people are doing it), but I think what it shows is, data structures can be difficult to do correctly.
In a worst case scenario you could write it in asm inside rust if you really need a low level control, or write it in C/unsafe rust and ffi or just write it in.
Basically worst case scenario in rust is writing something closer to C.
That isn't to say a narrow ecosystem is necessarily bad, it can often be good if a particular language is used for a specific domain as all the libraries and data structures will likely be a better fit for your problems. Going outside of those constraints can often be very punishing in those languages though.
My advice would be not to judge any language on how easy it is to implement a doubly linked list. 99% of code you write will likely not be that, and that particular data structure exposes a lot of choices and trade offs at a time when youd be better served learning other parts of the language.
IMHO Rust's lifetime analysis should consider borrows only at the point of dereference, not just whenever you encounter an & symbol. They already do that with raw pointers - you can have as many pointers as you want but you only need to mark `unsafe` if you actually dereference one. So at least someone on the team knows how to make that work functionally.
I'm sure you know this already, but for the people reading this: first of all "unsafe" is a very rare, and it's only "less safe" more than fully "unsafe"; ie it's still safer than C++.
And the second thing is that, often you don't have to drop into unsafe Rust, it's possible to achieve most stuff without it, but might incur a small performance cost (idk if some of those can be optimised away by compilers or not).
Python to Rust is a pretty radical swing from one approach to language design to another. I'd expect you could solve most of the maintenance problems with Python by switching to something statically typed but with garbage collection (e.g., C#, Java, or go), without incurring the costs of moving to Rust.
When a lot of what you're doing is interacting with low-level platform APIs, you end up having a lot of those unmanaged objects. After a certain point, the upsides of using a GC kind of disappear because you still have a lot of places you have to worry about those objects.
Of course, this can be worked around by providing managed wrappers around those unmanaged object, but at a certain point, it becomes easier to just drop down to an unmanaged but safe language (like Rust) that model the unmanaged resources more accurately. In my experience, it's somewhat easier to provide Safe Rust wrappers around your average Windows API than it is to provide a C# Managed Wrapper around the same.
---
And yes, go is special because it has very smol stacks, so doing any kind of FFI on it is a bad idea.
I'm genuinely curious as to what would make FFI in Rust easier than in C#, assuming an apples-to-apples comparison (i.e. use of "unsafe" and associated features in both cases"). Most complexity in P/Invoke shows up when you try to use it to automatically map data to managed data types; but in modern C#, you might as well just use raw pointers, stackalloc, spans etc.
...so requiring `use of "unsafe"` is often akin to forbidding Cargo/pip/NPM/etc. and then calling the language un-productive or faulting a procedural/imperative language for performing badly when you code as if you're writing Haskell.
https://www.hobofan.com/rust-interop/
https://areweextendingyet.github.io/
Using the ecosystem rather than reinventing it is a core tenet of Rust's value proposition.
Rust really does not limit you. Anything possible in C or C++ can be done in Rust if you're willing to use unsafe code.
Most of that difference is in things that happen at compile time, so this is not a question of Turing completeness.
Do you have any examples?
The heart of C++ is destructors: a bit of code that you can write and the compiler will ensure runs when code goes out of scope/is deleted. You can do this in C by remembering to manually call the right code when doing clean up, but it is easy to forget and thus error pron. (I think Rust has this too?)
C++ gives you the ability to do a virtual base class interface, which - as most people know - just means it writes a vtable behind the scene for you. Sometimes people write a vtable by hand in C: it is just a struct of function pointers, but the syntax to do it in C++ is a lot nicer. If you need an interface of some sort the win goes to C++ because the syntax is a lot nicer. (I'm not sure what Rust does about interfaces, I think it has something)
C++ gives you control over copying structs. In C structs are only copied member wise, if the struct has a pointer you need to keep track of both copies so you don't free it early. In C++ you write a copy function that will make a copy of the pointer. You can do this in C by remembering to call the right function when copying a struct, but the default is the wrong thing. (I'm not sure what rust has here, but at the very least the borrow checker will stop you from making a mistake)
C++ gives you move objects - a way to express that a struct is going out of scope, but only after a different one is taking over the contents. This is a variation of the previous, except that you know the original doesn't need valid data anymore and so you just copy pointers and null them in the original. C doesn't have this concept, you can get around it with use of pointers and manual copying of structs in the right places, but the code is ugly. (again, I'm not sure what rust does, if nothing else the borrow checker should allow the compiler to make some optimizations on this lines)
There are a lot more areas where C++ gives you syntax to write correct code that C does not. Rust intentionally doesn't have some of them (class inheritance has been abused often, but I still find it useful enough in a few cases that I think rust is wrong for throwing it out), and in other cases has come up with a better syntax. Overall I don't know enough about Rust to judge it, but I'll take C over C++ anyday.
Note, the above is about the advantages of C++ over C. C++ has a lot of warts that are out of scope for that discussion. I am not claiming C++ is perfect. If you are starting a new project you should seriously consider your language options - including some not mentioned here)
I'm somewhat confused about why it was downvoted - there is nothing there controversial at all.
[1] In my own toy language, I'm kinda leaning towards objects with destructors. Definitely without the footguns in C++, but destructors nonetheless.
Did you mean the opposite?
Rust doesn't have class inheritance, no, but often combining traits and delegating to a "parent" field works. Although sometimes that can be considerably more cumbersome, yeah.
With the C++ approach I've found myself overthinking the problem many times. But with the insight that pointers are just data, and memory management can be independent, it turns out that programming with raw pointers need not be hard. There is no problem passing a pointer without "move semantics" shenanigans.
I'm not saying that it has to be this way, but there is a reason why something like unique_ptr (that can be quite tedious to use in my experience) has become so popular in many projects - IMO it is overused, often leading to more typing work instead of less.
If one is sufficiently used to this way of modelling, it can come as a surprise that memory management needn't be so hard, and doesn't require smart pointers or anything, if the program design (global flow of data etc.) is sufficiently clear.
There is no sense, in C++, in which a naked pointer implies or suggests ownership. It is the opposite: the continued validity of a pointer value depends on ownership maintained elsewhere. Nowadays libraries keep track of ownership. Most commonly the library delegates that responsibility to Standard std::unique_ptr, for familiarity. Not doing that indicates something different in play.
(It is, in fact, UB even in C to copy the value of a pointer to an object that does not exist anymore. This is the case regardless whether it had pointed to or into a stack or a heap object.)
In C, there is no way to express library ownership of a pointer. So, in C there is always potential for confusion about ownership.
I give you one advice: Think twice before writing this way again. You are not putting enough effort into understanding what I'm trying to say, and coming across as an arrogant prick.
https://news.ycombinator.com/item?id=31494099
Admittedly, I didn't make my point sufficiently clear, but this isn't even about being right or wrong. (And, once more, I understand what you say. Stop belittling me.)
This sounds as insane to me as a carpenter who works with power tools saying. "Having safety measures which limits you and controls how you you have to do certain things does not sound appealing to those who need a house build, fast."
It's not good, and when a bridge falls over the results are a bit more... dramatic and undeniable - but it's not really my impression that other branches of engineering are particularly immune from corner-cutting and deliberate under-estimation.
Edit: though I'll say, just having someone "at random" say they expect better in their industry is an anecdotal evidence that it is at least a bit better. Also, you get to work outside. Truly, grass is greener on the other side of the road.
In case you haven't seen it, there's been some interesting progress on that front:
Believe it or not industry has and is continuing to adopt rust. Microsoft, AWS, government agencys in Europe, the Linux kernel itself (the only other language allowed there is C - think about it). It's really not all hype, people like it because it solves a class of problems from never happening while still performing very well.
I invite you to join the community and learn it. It's a lot of fun once you get proficient with it.
This is the ideal, but not always the reality. The Rust borrow checker isn't perfect, so sometimes it rejects code that should work perfectly fine. Hopefully as the language matures (Polonius, GATs, HRTBs…) these cases will become rarer.
Come to think of it, an even simpler example is a mutable iterator for a typical data structure. Such iterators usually require 'unsafe' code to implement, even though they are perfectly safe to use. https://stackoverflow.com/questions/63437935/in-rust-how-do-...
A lot of people don't seem to realize how easy it is to get UB in other languages. The C spec for example claimed not having a trailing newline at the end of a file was UB...
I also don't think this was an example of code that should compile but doesn't. Rusts' ownership rules make this task hard, but there are lots of people using doubly linked lists in rust... Yes they used unsafe code to do it, and yes it does compile .
The question was show us a case where the borrow checker was wrong.
I'm fully aware of this. That's why I put 'unsafe' in quotes.
However, it's surely fair to point out that you can't implement doubly linked lists or mutable iterators in Rust without giving up Rust's usual guarantee of memory safety. If this guarantee is not actually that big of a deal, as you appear to be suggesting, then why all the hype about it from Rust advocates?
>The question was show us a case where the borrow checker was wrong.
No, that was not the question. OP just asked for 'rejected code that should work perfectly fine'. There are of course loads of examples of such code. Perhaps the simplest is the case of mutable iterators that I mentioned. A correctly implemented mutable iterator is perfectly safe, but rejected by Rust's borrow checker unless certain parts of the implementation are marked unsafe.
And no, memory safety is a huge deal, it is just that the borrow checker cannot verify the soundness of certain code, meaning you have to provide the guarantees normally given to you outside 'unsafe' blocks.
Yes, this means that a few data structures require 'unsafe', but you should be creating safe wrappers around these structures; 'unsafe' won't propagate up your code and poison everything.
And I was just proving examples of such code for someone who asked. Honestly, some Rust folks get so defensive it makes them very prone to misinterpret simple factual statements about Rust as criticism.
Apparently you don’t disagree with any of the factual statements that I’m making. You just have some vague unsubstantiated feeling that I don’t ‘get’ Rust.
You're adding other claims and statements that make me question if you actually understand the thing you are criticising.
I will if the Rust community agrees on a lighter, less complex language core.
"Microsoft, AWS, government agencys in Europe, the Linux kernel itself (the only other language allowed there is C - think about it)."
Again, they are using only a subset of the language. Linus allowed it in the kernel once devs agreed only to use the Rust core features. They even had to make a new memory allocator, IIRC.
They also didn’t have to write a new allocator; they did extend the interface of the “alloc” library (which sits between core and std) which was then also accepted upstream.
It's also kind of normal to you know tweak a language so it integrates with an OS better... Even if they did change their allocator, who cares?
I think that a lot of complexity in Rust comes from many different ways to handle memory. You have your Arcs, Boxes, Cells, etc. Then you have a core "alloc" library.
Maybe if everyone agreed on a single reliable method to handle heap memory (since using stack is easy), Rust wouldn't be so hard to use.
The syntax also could be improved. Seeing <Box(T)> or whatever nested three or more levels deep hurts my eyes.
Boxes, cells, arcs, etc. exist for different purposes and if you'd take two hours to actually read about them and their uses, you'd understand why they exist.
> Having a complex programming language which limits you and controls how you use it does not sound appealing to those who need a feature done, fast.
See, I don't think Rust makes that _harder_ - I think it surfaces the real complexity, makes is undeniable. So far in my - by now 20 year old - career, when I've seen most teams faced with complexity that might either slow down a project, or be swept under the rug, the latter was always chosen.
There are _business reasons_ for that, software projects don't live in a vacuum - but those reasons are... _depressing_ at best - by far the biggest one I've seen is that a correctly estimated project would never be approved. Let's just say that figuring that out is a cognitive hazard that can easily increase risk of burning out - literally the sort of knowledge you're better off ignoring.
So ultimately my line of thinking is, Rust's problem in the business sense is basically the same as when you try to code in it: it _tells you that you're trying to sweep something under the carpet_. It tells you that your feature's cost is under-estimated. And to be fair: what can you do about it? The feature wasn't truly estimated by you. It was, almost certainly, estimated by your boss to be "one sprint at most," before he even asked you, and "please estimate this" has an expected answer, and giving any other one has a high social cost. And goddess protect you if your answer might call the entire business model into question.
I don't think any of us can change this, nor that the software engineering workforce is ready to push for changing this. Because even if we convince _our boss_ - the investors will just pick someone else, after all.
--
Anyhow, now you'd be excused in expecting me to advocate some sort of gatekeeping - but no, what I like about Rust is that it attempts to make programming more accessible in a _very different way_ to how many high-level programming languages did. For example:
- it's not _just_ a systems programming language. It doesn't divide programming into "stuff for anyone" and "eldritch monstrosities for the Chosen Ones" - eldritch stuff is just around the corner, in the same language, - it doesn't try to hide the complexity - it tries to give you tools to _explore it_, - and, expanding on the latter, its community values documentation and teaching over restricting use cases.
I don't think Rust is entirely _successful_ at that - but I think that the different model for accessibility is, if anything, more interesting than the borrow checker. I don't think we really need a single language - a garbage collector can be performant and useful, for example, and does it really _have to_ actually result in sweeping complexity under the rug?
Currently Rust is not as complete or well defined as Ada/SPARK or MISRA C/C++ combined with commercial analyzers (Astree for example). At the same time Rust is "too sound and rigorous" for mainstream programmers.
Rust advocates are in the losing battle of of forcing mainstream to adopt "it does not compile unless computer says its ready" style. Reliability and soundness comes with a cost.
Most software is not worth of the cost. When you adopt subscription model, fixing bugs is where the money is. If your app works flawlessly without updates, Apple removes it after few years.
If I was doing something high level, I would probably use Ocaml which has nicer features. If I wanted to write safe code, Ada offers a better experience with the availability of SPARK for parts I would probably end up wanting to prove. If I just want to write concurrent code with the certainty I could find someone to maintain it, Go seems the way to go.
Rust seems to want to be a replacement for Ada but seems to actually attract programmers used to high level language chasing the hype.
What’s the story with Rust and verification nowadays?
HPC, HFT, GPGPU, LLVM/GCC infrastructure, GUI, console SDKs, drivers SDKs, security certification ,....
I not not seeing Fermilab or CERN doing real time beam processing in Julia anytime soon.
Or stuff like having graphical shader debugging tools for Julia.
It is in progress but likely several years to go before a MVP is released. Ferrocene [1] is the primary effort that I am aware of and that seems to be making progress towards a verified rustc suitable for safety critical work.
Ferrous Systems is working with AdaCore and just released the Ferrocene Language Specification [2] to formally document the Rust subset that Ferrocene will use.
[1] https://ferrous-systems.com/ferrocene/
[2] https://ferrous-systems.com/blog/ferrocene-language-specific...
Gotta say SPARK does seem to provide much of what it claims. Interesting that NVIDIA seemed to be using it for their secure bits.
"From the data obtained, we can make the following key observations. First, there are 9 out of 72 rules for which violations were observed that perform significantly better (α = 0.05) than a random predictor at locating fault-related lines. The true positive rates for these rules range from 24-100%. Second, we observed a negative correlation between MISRA rule violations and observed faults. In addition, 29 out of 72 rules had a zero true positive rate. Taken together with Adams' observation that all modifications have a non-zero probability of introducing a fault, this makes it possible that adherence to the MISRA standard as a whole would have made the software less reliable."
[1] https://repository.tudelft.nl/islandora/object/uuid:646de5ba...
Dunno what you mean. I like Rust. I think it’s by far the best language in its niche, which contains exactly two languages: Rust and C++.
If what you’re doing doesn’t fit into that niche, that’s fine! Don’t use Rust.
Who is forcing anyone to do anything?
Year - Most Loved Pct. - Rank
2015 - 73.8% - 3
2016 - 79.1% - 1
2017 - 73.1% - 1
2018 - 78.9% - 1
2019 - 83.5% - 1
2020 - 86.1% - 1
2021 - 86.98% - 1Not claiming that this explains the entire increase in the percentage (I have no way of knowing) but I don't think this data contradicts my reasoning either.
I find Rust perfect for hobby projects because:
1. Squashing bugs that show up after the code successfully compiles (or, in Python's case, appears to work) is a big drain on motivation.
2. The ecosystem's focus on API stability means that, once it works the way I want, the costs of ensuring "it built/ran yesterday, so it should build/run today too" will be minimized.
3. I don't have to write as many unit tests to feel I can trust it with my data.
TL;DR: Once you're on the same wavelength as the compiler, Rust is great for projects where your motivation is purely intrinsic.
(Well, that and the compiler has been constantly improving. Things especially got much better after non-lexical lifetimes landed.)
It's pretty trivial to see that Rust adoption is increasing, so you can discount (1).
Is this weighted somehow by overall popularity?
Rust really is a great programming language that solves a lot of other problems other languages don't. It does so by introducing a pretty clever paradigm.
The rust community is the least toxic programming community I've ever seen. Leaps and bounds away from go lang, python, and light years away from c, etc.
Like use your head, is vba therefore the language which everyone tried and loved and had to move on from? You're trolling yourself lol. Rust is great but yes you have to learn it and yes that is tricky at first. Join a rust chatroom or discussion board and give it a whack.
Were you around when Scala was the end all be all of programming shiny things?
"Early on, Scala rode a wave of hype that frankly surprised even me: hype around pushing syntactic boundaries, hype around reactive architectures, hype around functional programming, hype around the Apache Spark project. Much of that hype has since died down, and there was a period of backlash and negativity both within the Scala community and outside of it. Since then, even the backlash has faded, and what is left is a reasonable, boring language steadily advancing and providing a great platform for general software engineering."
source: https://www.lihaoyi.com/post/TheDeathofHypeWhatsNextforScala...
Not every concern needs to be solved at source level. My brief crit of both Scala and Rust is that they do not take a modular approach and instead have opted for a 'comprehensive' approach that necessarily entails (arguably) unreasonable levels of complexity at syntactic and semantic layers of source code.
I think rust differs from scala in what it is trying to do. I also think rusts' complexity is backed by functionality that defines it's paradigm. Scala on the other hand has a few too many 'i think this would be nice to support' features in it that make it messy to deal with.
Rust imo isn't messy in that regard. Does scala still have it's place, sure. Does rust have it's place, yes.
Also if you read the posts on here, there's a lot less hype going for rust than the other way around. It's success isn't really due to it's hype, it's because people like what it does for them. Lots of people hate on it, usually baselessly.
You needn't use your real name, of course, but for HN to be a community, users need some identity for other users to relate to. Otherwise we may as well have no usernames and no community, and that would be a different kind of forum. https://hn.algolia.com/?sort=byDate&dateRange=all&type=comme...
Rust's "pretty clever paradigm" lifts a large set of low-level concerns into the application domain, and consequently makes them the responsibility of the application programmer.
This makes sense for a subset of programming contexts, where the application programmer needs to have and assert specific positions in those domains, in order to produce viable programs.
The problem is that, overall, very few programming contexts actually benefit from this level of specificity. An HTTP service implementing a business-level capability absolutely does not give a shit about ownership lifetimes. The fact that Rust "solves" this category of issues is completely irrelevant to this class of program.
How would you compare it to Typescript? Having become a recent convert, I feel the same way going back to Javascript now
You often end up with obscure issues that a good type system should prevent. Maybe because the third party typings for a package are faulty or incomplete, maybe because the compiler just gave up on a complex expression and fell back to any, or because the developer just gave up and used `as any`.
Typescript is also really constrained by keeping JS compatibility. A prime example is the lack of real sumtypes. Instead you have to use objects with a string tag and do if/switch on that tag to disambiguate the concrete type, which is incredibly awkward when compared to proper compiler sum type support.
I'd much rather use Typescript than Javascript, but it's far from perfect.
I don't know why but haven't seen many posts on how the combination of Rust's trait system, implicit conditional returns and strict enforcement of im/mutability of state allows one to handle significantly higher amount of states the application can take in the same amount of code. Other languages usually have you writing thousands of lines of verbose error handling and state validation code and traits allow for a superior way to compose behavior over standard interfaces / abstract classes.
Is your software more performant and does this translate to additional customers or reduced costs? Is your software more stable and does this result in reduced support costs or happier customers?
Testing effort is likewise not a decisive matter. In fact it's quite likely that what one wins time-wise on the testing side is lost on the development side.
That said, I think Go's simplicity has a lot of advantages over Rust for a great many use-cases. Imo Rust almost feels like a prototype for a great language which will finally get ownership-based memory management right. The goals of the language are admirable, and the tooling is great, but it's such a complex language once you start getting into topics like lifetimes and async.
I think it shines for certain use-cases where the tradeoffs it makes genuinely add value, but in a lot of ways I think it's more of a niche language for people who love esoteric programming topics rather than something with the potential to go truly main-stream.
What are the differences between an ADT (plus pattern matching i’d reckon?) in Rust/Swift vs the equiv in Go (tagged interfaces + switch statement)?
One has exhaustive matching at compile time, the other has a default clause (non exhaustive matching), although there’s an important nub here with respect to developer experience; it would be idiomatic in Go to use static analysis tooling (e.g. Rob Pike is on record saying that various checks - inc this one - don’t belong in the compiler and should live in go vet). I’ve been playing with Go in a side project and using golint-ci which invokes https://github.com/nishanths/exhaustive - net result, in both go and rust, i get a red line of text annotated at the switch in vscode if i miss a case.
Taking a step back, there isn’t a problem you can solve with one that you can’t solve with the other, or is there?
To take a step further back, why incomplete?
Also with Rust for instance you have more robust pattern matching. So you don't have to match only on type, you can match on complex criteria (i.e. foo is a Circle, with foo.radius < 10).
I find this type of programming very expressive and easy to reason about.
Yeah me neither, i’ve just been dabbling for fun recently. I’ve been dabbling with rust for longer
>> the Go way seems to have more boilerplate
…
switch t := s.(type) {
case Circle:
if t.radius < 10 {
fmt.Println("the rust syntax for this is sweeter")
}
…
https://go.dev/play/p/s4TTZeo7GseDefinitely less boilerplate in the rust version, but i don’t think i go along with it being incomplete or less clear.
Go: https://go.dev/play/p/s4TTZeo7Gse
Rust: https://play.rust-lang.org/?version=stable&mode=debug&editio...
For me, i reckon the Go type machinery is more verbose in this case, e.g. the isShape method to tag Circle as a shape - that just feels awkward to me.
The cyclomatic complexity is identical for both though.
Also I prefer with Rust-style sum types that the declaration happens in one place. In the Go version your Shape types could be scattered around all over the place, which makes it harder to parse and understand if you're reading unfamiliar code.
edit: e.g. https://go.dev/play/p/wDO5J8CElSC
enum Shape {
None,
Circle(radius: usize),
}
In your version we've lost the Shape concept, to make it more explicit, what's the idiomatic go version of: enum Shape {
Circle(usize),
Rectangle{length: usize, breadth: usize},
}
https://play.rust-lang.org/?version=stable&mode=debug&editio...In Go code will typically "offer" concrete types, and "accept" abstract interfaces. Abstractions over concrete types are expressed by consumers who want to operate on those types, rather than producers who provide implementations of them. So your Shape would probably end up an interface defined by whatever consuming code wanted to treat Circles and Rectangles equivalently.
E.g. if that means implementing low level things like cryptography APIs, or being able to define the exact memory layout of objects in memory or access raw pointers or write ASM inline then obviously that disqualifies ruby, python and js but it would mean Go qualifies.
The article is about a “messenger bot” for example and nobody’s complaining that it’s wrong to write such a thing in Rust.
The reality is that Rust is competing with Java and Go and Python for many things and its poor ergonomics are hobbling it.
I realize that Rust's compiler might catch more concurrency problems, but your comment is written as if you feel "blind" even writing single threaded code.
It's very common in Rust to do a big refactor or write a program from scratch and have it work on the first or second try, which may release a good amount of dopamine for some.[0]
Not saying the language is perfect, but it can feel pretty good, to the point of being addictive, while also freeing to know you can think less about the variants and let the compiler do it for you, and the reliability of the created program is usually pretty amazing. It can also be annoying, specially when you're learning it and try doing something in a way that's just not viable in an easy way (e.g. manually creating a Linked List).
[0] https://old.reddit.com/r/rust/comments/uixup6/just_wanted_to...
I feel like this article is written from a perspective of a library author that always starts with going for zero allocations generic API. In production apps you very rarely do that, usually it's plenty fast anyway.
This type of thing comes up of often when people try the language. They re-implement some part of a program, originally written in a fast GC language, and then wonder why it’s slower.
I feel like the power of the language comes through in specific workloads, or when you take the additional time to avoid naive code. That’s why it is so verbose and rich, it gives you more control. And this is something that advocates often clearly state.
Like I posted earlier, you don't do this everywhere, just some sporadic use where it makes life a lot easier. It doesn't have to be all or nothing.
Was going to post the same comment. Most of my hobbyist Rust programming has been via the Actix Webframework and I only run into the most trivial of borrow checker issues. I guess my projects are not complex or interesting enough :).
For instance, I haven't yet had to debug weirdly muting memory, deal with the immense nuanced possibilities of doing the same thing (there's a reason for CPP core guidelines), stuff like the rule of five, writing cross platform cmake files that include various libraries, ...
Not proof for a general statement, but another example from a Rust adaptor
Imo I write programs faster than other languages because the compiler helps me out. Your mileage may vary.
Incorrect. This handler-dispatcher problem illustrated in the article is utterly trivial in C++ and many programming languages. No need to struggle and stretch your brain as if you are in the Math olympiad.
I am learning Rust myself and I think Rust fans are spreading misinformation and propaganda by saying Rust makes things easier than other languages. No, Rust makes things VERY difficult - and you need to study and learn the Rust way of doing things - which is significantly different from other programming languages.
We need a BIG design patterns for Rust book - which takes lots of common design problems and shows the idiomatic Rust way of doing it.
But just stating that C++ code for a given design problem is harder than Rust is utterly wrong and demonstrably false. Rust tooling is definitely simpler. Rust coding is definitely not.
I don't think anyone is trying to claim that rust is some trivial language. It's not. But it makes systems level concerns explicit, flying blind is much harder in my opinion. The complexity is technically the same, but the language has training wheels that other languages don't.
This is absolutely not true. Something hard in Rust but almost trivial in C++ (via fold expressions): mapping or folding a function or operator over a tuple of heterogeneous types. E.g. to sum over a tuple of arbitrary numeric types:
auto mySum = std::apply([](auto... x){ return (x + ...); }, myTuple);Fwiw rust doesn't let you dynamically index tuples, because rusts' take on tuples is different.
Should your tuple actually be a struct with a "sum" method on it? Imo probably. Or should you have your numeric types be the same type for better memory layout, maybe...
Just because another language let's you do something doesn't mean you should do it. Kind of like in js, does it make sense to divide a number by a string(not sure if you can do this but guessing it's valid js), probably not, is it a feature or a bug, you decide. Should this be part of say the kotlin standard, probably not.
That is not true of C++. There are many valuable things that are much easier to express in C++ than Rust, owing to C++ being a significantly more expressive language. Rust also doesn't make it easy to write software where ownership is intrinsically ambiguous and must be algorithmically resolved at runtime without wrapping the object, a common case e.g. for high-performance storage.
I would agree that everything is harder in C, though.
I really enjoyed Haskell when I tried it years ago (2004) and I definitely agree that Rust is much more apropos to the mainstream.
Love it!
...
I spent a lot of time reading r/rust, various blog posts before going beyond helloworld in it.
To me it's in the same category as Scala (ZIO) or TypeScript. Both are very powerful, a joy to work with them, until the low-leven limitations hit in (JVM or JS).
However I don't interpret that as a sign of oh we need to go back to assembly, but more like, okay, we need to accept that our tools and the problems we use them on are not in harmony (yet).
Though I might argue that one of Scala's biggest issues in my eyes, performance, is mostly _not_ a JVM limitation.
For example, a Scala for-loop calls functions on each iteration, and immutable containers need to be garbage collected for each modification. Both of these could be compiled away in many common cases (like C++ or Rust do, but Scala's compiler doesn't, unless they've changed that in the last couple of years).
Which is a shame because I did a hobby project with it and it was super fun and liberating compared to old java.
Well, they didn’t break the existing language, so not sure. It depends on what do you find readable/difficult. Because contrary to the usual opinion on the language, I believe it is not “difficult” - it has much fewer exceptional rules than Java for example. Sure, some features are more expressive and that comes with big responsibility, but to actually answer your question, some implicit usage is indeed cleaned up making it much less magical-looking.
But scala 3 has been a very huge update, including having a new compile flag that will turn to language “null-safe” (so a nullable String will have String | Null as a type). So it might be worth it to have a new look at the language.
And for TS I don't think I have to mention the quality of the underlying JS ecosystem :)
On the other hand, of course Rust is still on 1.x, GAT is still on the roadmap (though the RFC recently entered into final comment period (or how it's called), yaay!, and then a bunch of legitimate criticism was submitted..., so it might still take year(s))
If you ever read, I think it was Modern C++? Where they point out the huge "trick" in C++ was someone figuring out you could make a compile time branch by declaring arrays of size 0 or some such nonsense. They then wrapped that feature in a template so you could then try to use it. At some point they formalized it so it's no longer based on arrays of size 0 but still, read any boost library and look at how unreadable it is. It might be nice to use, but it shouldn't be so hard to write!
But, I think the fact that it is hard to write brings joy indirectly to many programmers. They get a dopamine hit for "solving the puzzle of finally getting their cryptic incantation to work". Maybe they write a bitset class. It takes 500-1000 lines of code. Or maybe they make a lighter weight fixed size array and again it's 1000+ lines of template code. They forget that the goal of coding is shipping, not having fun solving the incantation puzzle.
It doesn't seem like it take 1000+ lines to do these things.
The author of a library with wide usage spending hours refining a method/class/function to it's most optimzied form may actually be worth the time because that effort is amortized over hundreds or even thousands of applications. The ROI is much higher in that case.
Determining when it's correct to make that tradeoff is an important part of the job. Boost probably makes the correct tradeoff. But your average C++ application dev might need to make a completely different one.
It's a matter of style and character how you cultivate new skills, and Rust wants you to cultivate them in a certain, some people are just not made for. YMMV.
But if you deviate from those, into higher level programs, a language with garbage collection will always be much more productive than Rust. So we have a set of people doing the things that Rust does best, and celebrating that they have a great language, and a set of people trying to fit the square language into a round hole, and complaining that it doesn't fit at all.
Added to that, there is a wide space of problems where high-level languages do not have appropriate support, but you can always hack your way in with a low level one. Those are the worst, because there is just no good option, there's just one that you can beat into working.
What I've found good about rust is its modern toolchain and documentation.
I have spent most of my career in C, C++, Objective-C and have recently tried Zig, which I enjoyed, possibly because of it's brevity, and I read through the Jakt programming language docs, which was much more familiar to me but I think if you only used Rust with ARC it would be a simple language to adopt so that's not really a fair comparison.
I think what I really need is a project rather than learning resources, with time being our greatest enemy, I need motivation to get over the hump so to speak.
(Like I said, I might not be smart enough, or I might just be profoundly lazy).
Thanks for your reply.
Moreover, a lot of the libraries in rust needs you to understand the type system thoroughly sometimes to use them, and some of them use the typesystem to enforce some specific behavior (without telling you :-)). For example, the logger mechanism in rust makes it very hard to dynamically change the logger implementation at run time but it doesn't explain why (in the end, I think it has to do with thread safety, but I'm not sure).
It took me about the equivalent of 30 full days to get there. Although I'm an experienced programmer (C++,assembly,Java,python,R), the last 15 years have been python 99%. Had I continued with C++ all those years, I'm sure I'd understand rust much better.
So, just keep going and really listen to the borrow checker. The thing is really smart and sometimes, after a lot of pain, you understand that your own mental model was wrong :-)
Mainly because logger is a static value, if you really want to change your logger at runtime, then you have to pay a little bit for synchronization (i.e. locking with mutex), other than that, it's not that hard.
Did you think that such a group of people, who place their love for the language above practical things like readability, would come up with a new language that cared about the user-experience[1]?
As we see all the time WRT to programming languages, readability is more important than the more abstract stuff.
> I hear all the arguments about CVEs and wonder if rust will reduce the number of these problems simply by disabling the programmers that create them.
That sounds like a different way of saying "the global number of CVEs will be reduced by reducing the number of applications written". After all, if you "disable" the programmers who write systems programs, they aren't going to get magically replaced by programmers who don't write systems programs.
You're just gonna have fewer programmers.
[1] A language is an interface between a user and their problem. If this is not highest priority of a language design, the language may never take off in any meaningful sense. See Monads.
Elaborate?
I got that, but the point is still very much relevant. If places switched to Rust from C++ (or Go, or C), they'd write less software because there will never be as many people who understand Rust as there are people who understand Go.
If it was at all easy to pick up there'd be a fewer stories from people who tried learning it and abandoned the effort.
I cannot think of any person who reported abandoning Go because it was too hard to learn.
Readability is an incredibly subjective thing. For example, APL might look like an absolute mess to most people but to the people who know it, it's incredibly easy to read. All "readability" means in this context is that it's familiar to you.
In my opinion, the only truly hard to read languages are languages that require you to keep large amounts of context in memory while reading a specific part of the codebase, be it due to lack of support for abstractions for proper encapsulation, messy overloading, insane inheritance hierarchies, or something else.
EDIT: Readability also requires you have a codebase that's well written, and even that's subjective.
But if we use that as a bar ("you have to know it"), then all languages are equally readable.
Pretty much all the popular languages converge on similar syntax an/or grammar.
You can say that it is because that particular set of syntax is the first, or you can say that languages that didn't have similar syntax was abandoned by developers.
There is an equal evidence/lack of evidence for either claim.
There is a balance between verbosity and conciseness that makes code more or less readable to different people.
If you have few experts who are maintaining a codebase over a longer time, then verbosity gets in the way. If you have a wider skill distribution and fast turnover, then you want verbosity.
Additionally I think there are more objective features. Like ambiguity, simplicity, formatting, naming, visual hierarchy...