jkelleyrtp
9 months ago
"There are only two kinds of languages: the ones people complain about and the ones nobody uses".
---
Glad to see fluffy negative articles about Rust shooting up the first slot of HN in 20 minutes. It means Rust has made finally made it mainstream :)
---
The points, addressed, I guess?
- Rust has panics, and this is bad: ...okay? Nobody is writing panic handling code, it's not a form of error handling
- Rust inserts Copy, Drop, Deref for you: it would be really annoying to write Rust if you had to call `.copy()` on every bool/int/char. A language like this exists, I'm sure, but this hasn't stopped Rust from taking off
- Fetishization of Efficient Memory Representation: ... I don't understand what the point is here. Some people care about avoiding heap allocations? They're a tool just like anything else
- Rewrite anything and it gets faster: okay sure, but there are limits to how fast I can make a Py/JS algorithm vs a compiled language, and Rust makes writing compiled code a bit easier. People probably aren't rewriting slow Python projects in C these days
- Rust is as complex as C++: ...no, it's not. Rust really hasn't changed much in the past 6 years. A few limitations being lifted, but nothing majorly new.
- Rust isn't as nice of community as people think: subjective maybe? People are nice to me at conferences and in discussion rooms. There's occasional drama here and there but overall it's been pretty quiet for the past year.
- Async is problematic: Async Rust really is fine. There's a huge meme about how bad it is, but really, it's fine. As a framework author, it's great, actually. I can wrap futures in a custom Poll. I can drive executors from a window event loop. Tokio's default choice of making `spawn` take Send/Sync futures is an odd one - occasionally cryptic compile errors - but you don't need to use that default.
I'm unsure why this article is so upvoted given how vapid the content is, but it does have a snappy title, I guess.
hyperbrainer
9 months ago
> Rust is as complex as C++: ...no, it's not.
Maybe not yet, but it is heading in that direction; and I only say this because of the absolutely giant pile of features in unstable that seem to be stuck there, but I hope will eventually make its way to stable at some point.
> Async Rust really is fine
I dunno. Always thought it was too complicated, but as another person pointed out avoiding Tokyo::spawn solves many issues (you said this too, I think). So maybe, not Rust's fault :D
Diggsey
9 months ago
> Maybe not yet, but it is heading in that direction;
It's definitely getting more complex, but C++ has a huge lead haha. C++ is like a fractal in that you can look at almost any feature closer and closer to reveal more and more complexity, and there are a lot of features... Here's a page on just one dark corner of the language: https://isocpp.org/wiki/faq/pointers-to-members and it interacts in interesting ways with all the other corners (like virtual vs non-virtual inheritance) in fun and exciting ways...
Also, there are far more ways to cause UB in C++. Rust has a big lead on formalizing what constitutes UB, and even those rules you only need to learn if you are using "unsafe", whilst in C++ you don't have that luxury.
tialaramex
9 months ago
> Also, there are far more ways to cause UB in C++.
As well as lots of Undefined Behaviour, C++ also has what its own experts call "False positives for the question is this a C++ program" the Ill-Formed No Diagnostic Required features, nothing like these exist in Rust, they're cases where you can write what appears to be C++ but actually although there are is no error or warning from the compiler your entire program has no meaning and might do absolutely anything from the outset. I've seen guesses that most or even all non-trivial C++ invokes IFNDR. So that's categorically worse than Undefined Behaviour.
Finally, C++ has cases where the standard just chooses not to explain how something works because doing so would mean actually deciding and that's controversial so in fact all C++ where this matters also has no defined meaning and no way for you to discover what happens except to read the machine code emitted by your compiler, which entirely misses the point of a high level programming language.
One of the things happening in Rust's stabilization process is solving those tough issues, for example Aria's "Strict Provenance experiment" is likely being stabilized, formally granting Rust a pointer provenance model, something C++ does not have and C23 had to fork into a separate technical document to study.
googh
9 months ago
Most (if not all) of your posts here on HN boil down to "C/C++ bad, Rust good". I wonder what you are trying to achieve by this, but I assure you that this does not do Rust any favor other than giving the impression that the Rust community is obnoxious.
Ukv
9 months ago
I found their comment an interesting contribution to the discussion, pointing to a couple of specific pitfalls in C++. It's not just an empty "C/C++ bad, Rust good", and I don't see why it'd give the impression of an obnoxious community.
googh
9 months ago
I just wrote that as an observation, and I did not mean to offend the parent.
Now, let me explain why I felt that way. First and foremost, the phrase "undefined behavior" only applies to C and C++ because the specifications of those languages define it. The statement that Rust has no UB does not make sense because Rust has no specification, and all behavior is defined by the default implementation.
For example, C/C++ specifications state that using a pointer after calling "free()" on it is UB. But an implementation can make it well-defined by adding a GC and making "free()" a no-op. Hence, memory safety is entirely orthogonal to UB.
Another example: signed overflow being UB is not a memory safety problem unless the value is used for array indexing. Also, it is possible to enable bounds checking in STL containers (like _GLIBCXX_ASSERTIONS).
It seems like that a lot of Rust fans read John Regehr's posts and use "undefined behavior" as a boogeyman to throw shade at C/C++. They repeat the same points ad nauseam. It also helps that the phrase "undefined behavior" evokes strong emotions (eg., "nasal demons"). I see the parent commenter doing this frequently and sometimes[1] even in the C++ subreddit (of all the places!). How is this not obnoxious?
Here[2] is another person doing the same, but in a spicier tone. Linked lists and graphs are safe if you have an isoheap allocator (look at Fil-C).
You can say that it is moral to endlessly reiterate the problems of unsafe languages, because it could lead to more secure software. But see the reply to my other comment by "hyperbrainer"[3] which says that Rust is "completely" memory safe, which is entirely wrong[4]. It is hard not to suspect the motives of those who claim to be concerned about memory safety.
[1] -https://old.reddit.com/r/cpp/comments/1fu0y6n/when_a_backgro... [2] - https://news.ycombinator.com/item?id=32121622 [3] - I am unable to reply because of the depth. [4] - Rust requires unsafe to do a lot of things which can be done in safe code in a GC'd language. Thus, unsafe is pretty common in Rust than most GC'd languages. If a segfault can literally kill a person, it is absolutely immoral to choose Rust over Java (it does not matter that Rust "feels" safer than Java).
tialaramex
9 months ago
I really am interested in what Safer C++ proposes for [1], but I never found out.
Your point [4] is very silly because you're assuming that while the unsafe code implementing a safe Rust interface might be flawed the code implementing a safe Java interface such as its garbage collector (which will often be C++) cannot be. As we'd expect, both these components are occasionally defective, having been made by error prone humans, such flaws are neither impossible nor common in either system. There are indeed even safer choices, and I've recommended them - but they're not Garbage Collected.
> First and foremost, the phrase "undefined behavior" only applies to C and C++ because the specifications of those languages define it.
Nope, those words have an ordinary meaning and are indeed used by Rust's own documentation, for example the Rustonomicon says at one point early on, "No matter what, Safe Rust can't cause Undefined Behavior". The purpose there is definitional, it's not a boast about how awesome Rust is, it's a claim that if there is Undefined Behaviour that's not because of the safe Rust, there's a soundness problem somewhere else.
> Another example: signed overflow being UB is not a memory safety problem unless the value is used for array indexing
This is wrong. Because Signed Overflow is UB the C++ compiler is allowed to just assume it will never happen, regardless of the systemic consequences. What that means is that other IR transformations will always be legal even if they wouldn't have been legal for any possible result of the overflow. This can and does destroy memory safety. Actually it would be weird if somehow the IR transformations always preserved memory safety, something they know nothing about, despite changing what the code does.
rascul
9 months ago
> The statement that Rust has no UB does not make sense because Rust has no specification, and all behavior is defined by the default implementation.
It is in the reference.
https://doc.rust-lang.org/reference/behavior-considered-unde...
Ukv
9 months ago
> The statement that Rust has no UB does not make sense because Rust has no specification
I don't think it was claimed that Rust has no UB in this conversation, only IFNDR.
From what I can tell, Rust does document a set of "behavior considered undefined" like using unsafe to access misaligned pointers. For practical concerns ("could code optimization change these semantics?", "is this guaranteed to work the same on future compiler versions?") it seems reasonable to me to call that undefined behavior, and to say that Rust doesn't have much of it.
> I see the parent commenter doing this frequently and sometimes[1] even in the C++ subreddit (of all the places!). How is this not obnoxious?
Both their comment here and their reddit comment look fine to me. Something like "C++ sucks, switch to Rust!" would be annoying, but specific relevant technical comparisons ("In Rust for comparison the static growable array V isn't dropped when the main thread exits [...]") seem constructive.
> Rust requires unsafe to do a lot of things which can be done in safe code in a GC'd language. Thus, unsafe is pretty common in Rust than most GC'd languages. If a segfault can literally kill a person, it is absolutely immoral to choose Rust over Java (it does not matter that Rust "feels" safer than Java).
Java does technically have the Unsafe class for low-level unsafe operation and JNI to interoperate with C/C++/assembly.
I'd expect that the average Rust program makes more use of unsafe, but largely just because the average Rust program is lower-level (including, increasingly, parts of the Linux and Windows kernels). It's unclear to me whether the same program written in Java or Rust would ultimately prevent more bugs.
umanwizard
9 months ago
> Now, let me explain why I felt that way. First and foremost, the phrase "undefined behavior" only applies to C and C++ because the specifications of those languages define it. The statement that Rust has no UB does not make sense because Rust has no specification, and all behavior is defined by the default implementation.
There are at least three classes of definedness of behavior:
1. The behavior of a program is defined by a spec.
2. The behavior of a program is not formally defined by a spec, either because the language has no spec or because it's imprecise, but it's defined in a sociological sense: that is, if a compiler doesn't follow the apparent meaning of the program, the people who develop the compiler will consider it a bug and you can report it to mailing lists or GitHub and probably get support.
3. The behavior is definitely undefined: a compiler can do anything in response to the program and the developers of the compiler will not consider it a bug.
C++ has a lot of 1, comparatively not a lot of 2, and a lot of 3.
Rust has none of 1, a lot of 2, and a lot of 3. But safe Rust has very little of 3.
tialaramex
9 months ago
> Most (if not all) of your posts here on HN boil down to "C/C++ bad, Rust good".
I haven't measured but it's easy to say categorically that it's not "all" unless somehow my posts about network protocols, aeroplanes, security and psychology among others fall into this vague category.
And yes, like Ignaz Semmelweis I can see an obvious improvement to how my profession does what it does and it's infuriating that the response from many other practitioners is "No, I don't like change, therefore you're crazy for explaining why I should change"
Ignaz Semmelweis died in an asylum. But on the other hand while Ignaz was correct and his proposals would have worked he couldn't explain why because germ theory was only confirmed after he died. Rust isn't in that situation, we know already exactly what the problems are with C++. So that means I can tell you not just that using C++ is a bad idea, but why it's a bad idea.
googh
9 months ago
Most HN users already use languages with GC which are more memory safe than Rust. People still use C++ either because they are maintaining existing code, or they work in domains where memory safety is not really necessary (games, HFT, ML). Apart from these, C++ is rarely used in the real world.
> practitioners is "No, I don't like change, therefore you're crazy for explaining why I should change"
Who exactly are you referring to here? Your co-workers? LLVM maintainers? or the Linux kernel developers? Please be more precise.
hyperbrainer
9 months ago
What is "more memory-safe than rust" supposed to mean? Rust is completely memory-safe.
tialaramex
9 months ago
Only safe Rust can guarantee this, and only as a consequence of any unsafe Rust being correct.
Most of the popular Garbage Collected languages of course also have a way to escape, in some cases via an "unsafe" keyword or magic unsafe package to a language where the same safety rules do not exist, in this sense the difference in Rust is that it's the same language.
I'd actually say the more memory safe option would be a language like WUFFS where it pays a high price (generality) to deliver categorically better safety and performance. Most software could not be written in WUFFS but also most of the software which could be written in WUFFS isn't.
CryZe
9 months ago
> Maybe not yet, but it is heading in that direction
About 95% of the unstable features lift limitations that most people expect not to be there in the first place. I'm not aware of all too many that aren't like that.
faitswulff
9 months ago
> Maybe not yet, but it is heading in that direction
When people say that Rust is complex, they often neglect to differentiate between implementation complexity and developer facing complexity. The implementation complexity is growing in part to support the end user simplicity. I also don't understand why anyone feels the need to know every feature of the language. You can just learn about and use the features that you need.
jiggawatts
9 months ago
That only works if you sit in isolation on a mountain and start with no_std and write everything else from scratch, yourself.
The majority exist in a community and have to collaborate with others. They have to deal with the code written by others, code which may use any language feature.
Every developer doing serious work will trip over every available language feature eventually.
faitswulff
9 months ago
> Every developer doing serious work will trip over every available language feature eventually.
Steve Klabnik:
“Just to provide another perspective: if you can write the programs you want to write, then all is good. You don't have to use every single tool in the standard library.
I co-authored the Rust book. I have twelve years experience writing Rust code, and just over thirty years of experience writing software. I have written a macro_rules macro exactly one time, and that was 95% taking someone else's macro and modifying it. I have written one proc macro. I have used Box::leak once. I have never used Arc::downgrade. I've used Cow a handful of times.
Don't stress yourself out. You're doing fine.“
https://www.reddit.com/r/rust/comments/1fofg43/i_am_struggli...
dartos
9 months ago
> Maybe not yet, but it is heading in that direction
I have little doubt that Rust will end up being as complicated as C++ eventually, but a big difference is how explicit and well documented the discusson of new features are.
The Rust RFCs provide a ton of context to almost every feature of the lagnuage. I find that historical context extremely helpful when trying to figure out why something is the way that it is.
There may be something like that for C++, but I feel like a lot of it is "you had to be there" kind of reasons.
pjmlp
9 months ago
ISO Rationales and papers.
dartos
9 months ago
Yeah I’m sure they exist, but googling “C++ ISO Rationales” doesn’t give me them.
Searching for “Rust RFCs” reveals a git repo with thousands of markdown files describing features and their motivations with links to discussions.
pjmlp
9 months ago
Because ISO processes are only open to those in the know.
Same applies to Ada, C, Modula-2, Pascal, Fortran, Algol, Cobol,.....
dartos
9 months ago
That's... what I originally said... "in the know" and "you had to be there" are effectively the same statment
It's is exactly why I feel more comfortable with complexity creep in Rust as opposed to C++, since I can easily find and read the rationale for just about every feature.
pjmlp
9 months ago
No they aren't, those "in the know" have access to ISO servers, mailing lists, meeting minutes, paper votes, and related content.
Some of the public C++ stuff:
https://www.open-std.org/jtc1/sc22/wg21
Some of the public C stuff:
https://www.open-std.org/jtc1/sc22/wg14/
Some of the public Ada stuff:
https://www.open-std.org/JTC1/SC22/WG9/
And so on.
Those "in the know" have access to the stuff that is beyond that.
However that is already plenty of stuff publicly available at those https://www.open-std.org subsites as well.
dartos
9 months ago
I don’t really know what your argument is
> Those "in the know" have access to the stuff that is beyond that.
Yeah “you have to be there”
But these are all great!
It’s a shame they’re not as discoverable.
s17n
9 months ago
> Fetishization of Efficient Memory Representation: ... I don't understand what the point is here. Some people care about avoiding heap allocations? They're a tool just like anything else
The point is that dealing with the Rust borrow checker is a huge pain in the ass and for most Rust applications you would have been better off just using a garbage collected language.
CryZe
9 months ago
> huge pain in the ass
Maybe if you structure your code weirdly? I haven't encountered a major borrow checker issue that I couldn't easily resolve in many years.
delifue
9 months ago
It's not appropriate to say that "having trouble with borrow checker means code is wrong". Sometimes you just want to add a new feature and the borrow check force you to do a big refactor.
tinrab
9 months ago
I hear this constantly but never see any examples of what they actually mean, or it's coming from misunderstandings of what the language is. I've seen people say how well the async code could be if Rust got a garbage collector. For the borrow checker specifically, I think it's important to understand smart pointers, Cell/RefCells, other primitives, and the fact that you don't have to solve everything with references.
RandomThoughts3
9 months ago
> it's coming from misunderstandings of what the language is
“You are just not holding it right.”
Rust borrow checker indeed does force you to make contorsion to keep it happy and will bite you if you fail to take its particularity into account. It’s all fine and proper if you think the trade-off regarding safety is worth it (and I think it is in some case) but pretending that’s not the case is just intentionally deluding yourself.
The people here implying that the BC forces you to use a good architecture are also deluding themselves by the way. It forces you to use an architecture that suits the limitations of the borrow checker. That’s pretty much it.
The fact that such delusions are so prevalent amongst part of the community is from my perspective the worst part of using Rust. The language itself is very much fine.
tinrab
9 months ago
Can you give me an example of what the borrow checker prevents you from doing without calling Rust developers delusional? The hardships are way overstated, in my opinion. One issue I can think of newcomers might have is immutable and mutable references. You can't borrow as mutable something already borrowed. Let's say you have a reference to a Vec element, then you add an item to Vec. The realloc could invalidate that reference, which Rust prevents. Using Cell/RefCell also helps if you don't want to deeply nest &mut. Rust is definitely hard, but after a while it's fine and you kind of get how even if using another language you still have to think about memory.
RandomThoughts3
9 months ago
I’m not calling Rust developers delusional. I’m calling people pretending the borrow checker doesn’t force you to specifically architecture your code to suit it delusional.
> Rust is definitely hard, but after a while it's fine and you kind of get how even if using another language you still have to think about memory.
That kind of comment is a typical exemple. It’s not that you have to think about memory. You have to understand the exact limitations of the analyser Rust uses to guarantee memory safety. I don’t understand why it’s so hard to accept for some part of the Rust community.
goku12
9 months ago
The advantage of satisfying the borrow checker isn't all that obvious. The BC is designed to make the program behave well with the fundamental machine model of a common computing device. You may be able to get away with spaghetti code for a new feature in a GC-based language. However my experience is that such technical debt grows over time and you're forced to carry out a massive refactor later anyways. GC isn't going to help you there. You might as well refactor the code in the beginning itself with the guidance of the BC in order to avoid pain in the end. This is why Rust programs have a reputation to run correctly almost always if they compile.
And as the other commenter said, the borrow checker isn't all that hard to satisfy. BC complaints are often related to serious memory handling bugs. So if you know how to solve such bugs (which you need to know with C or C++ anyway), BC won't frustrate you. You may occasionally face some issues that are hard to solve under the constraints of the BC. But you can handle them by moving the safety checks from compile-time to runtime (using RefCell, Mutex, etc) or handle it manually (using unsafe) if you know what you're doing.
Like the other commenter, I find some of the complaints about programming friction and refactor to be exaggerated very often. That's unfair towards Rust in that it hurts its adoption.
iknowstuff
9 months ago
I haven’t had to „deal with” the borrow checker since like 2018. It’s quite smart
XorNot
9 months ago
Having just delved into Rust a little (and then given up and decided to learn Dart/Flutter for more practical applications development - I don't need another language to make command line tools in), this one I did feel while I was going through documentation.
The problem is most of the important problems you deal with while programming require heap allocations: i.e. a lot of Rust advice is liable to lead you astray trying to find over-complicated solutions to optimizations you probably don't need up front.
So in terms of systems programming, Rust is technically good here - these are all things you'd like to do on low level code. On the other hand if you're making a bunch of web requests and manipulating some big infrequently used data in memory...Box'ing everything with Arc is probably exactly what you should do, but everyone will tell you to try not to do it (and the issue is, if you're like me, you're coding in the "figure out what and how to do it" phase not the "I have a design I will implement optimally" phase).
jkelleyrtp
9 months ago
I mean, maybe?
If you come into Rust thinking you're going to write doubly-linked lists all day and want to structure everything like that, you're going to have a bad time.
But then in python you run into stuff like:
```
def func(list = []):
list.append(1)
```and list is actually a singleton. You want to pull your hair out since this is practically impossible to hunt down in a big codebase.
Rust is just different, and instead of writing double-pointer code, you just use flat structures, `Copy` keys, and `loop {}` and move on with your life.
Izkata
9 months ago
FYI this site doesn't use ``` for code blocks, it uses indentation (two spaces).
mewpmewp2
9 months ago
A bit off topic, but how do people usually write code here or on Reddit, I always find it to be really cumbersome to make sure there's two spaces etc in front of everything? Is there some formatting tool that I'm not aware of that everyone else uses?
Because in both forums I keep coming back to edits, and it takes forever to edit some of the things, manually. I feel like I'm being stupid or the UX of all of that is just so terrible.
steveklabnik
9 months ago
I write it in play.rust-lang.org, then indent using the vim keybindings. I do this even for not rust code.
satvikpendem
9 months ago
I actually use a formatting tool online if on mobile, or just vim if on the computer, which can add two spaces in front of every line.
Izkata
9 months ago
> or just vim if on the computer
I use Firefox + Tridactyl + the native extension, so with the cursor in any text field I can hit Ctrl+i and it pops up a gvim window with the contents of that text field. When you save+quit, it copies the contents back into the field.
So glad someone figured out how to do this again once Vimperator died.
umanwizard
9 months ago
I paste the code into an invocation of
sed s/^/ /
jasomill
9 months ago
Specifically:
1. Copy code to clipboard.
2. From a shell prompt on macOS,
pbpaste | sed 's/^/ /' | pbcopy
Linux (Wayland), wl-paste | sed 's/^/ /' | wl-copy
Linux (X11), xclip -o -se c | sed 's/^/ /' | xclip -se c
Windows (PowerShell), Get-Clipboard | % { $_ -replace '^',' ' } | Set-Clipboard
3. Paste into HN.umanwizard
9 months ago
Thanks, I didn't know about xclip -se c
I've been typing out "-selection clipboard" this whole time!
pjmlp
9 months ago
Code editor and then paste.
fiedzia
9 months ago
> this is practically impossible to hunt down in a big codebase
use linters, they keep getting smarter
n_plus_1_acc
9 months ago
rustc is a good smart linter
junon
9 months ago
And if you're really wanting to be stringent, clippy exists for more subjective or more expensive lints. And it's also very good.
s17n
9 months ago
I have literally never used a doubly-linked list in my life, and I'm pretty sure that most programmers can say the same thing.
As for the example... yeah, Python is pretty terrible (for writing production codebases, I think its a great language for short-lived, one-person projects). Interesting that you mention Python because if you're considering Python and Rust for the same use case that's pretty bonkers, for anything that you might possibly have used Python to do there are many more natural choices than Rust. If you wouldn't have done it in C/C++ ten years ago, you probably shouldn't be doing it in Rust today.
user
9 months ago
pjmlp
9 months ago
If the programmers have a proper degree, they surely have used them, additionally they probably have done it inderectly, depending on what languages they use.
johnnyanmac
9 months ago
Yeah. I wouldn't use Rust as a scripting language for that reason. But some critical applications want that enforced correctness and (hopefully) proper performance to be guaranteed if you pass the compiler.
I want to eventually join the "50 engines for every game" race that is rust gsme engineer development, but I'm sure not going to have the fast iteration part of design be done in Rust. The renderer and all the managers should be absolutely solid, but some parts of games need you to break stuff quickly.
s17n
9 months ago
Enforced correctness is great. Manual memory management isn't appropriate for most applications (games of course are an example of where it is!)
mondobe
9 months ago
> Rust really hasn't changed much in the past 6 years.
Even more importantly than this, Rust has a major emphasis on backwards compatibility. The author mentions a "hamster wheel" of endless libraries, but, in Rust, nothing's forcing you to switch to a newer library, even if an old one is no longer maintained.
In general, the complexity of your project is completely up to you, and (at least to me) it seems like a lot of the new features (e.g. generator syntax) are trending towards simplicity rather than complexity.
ggregoire
9 months ago
> I'm unsure why this article is so upvoted given how vapid the content is, but it does have a snappy title, I guess.
rust, sqlite, htmx... there is a small list of techs that always get massively upvoted on hn, whatever the content or quality of the article.
marcosdumay
9 months ago
Well, if the entirely of that list is as awesome as those 3, then it's a good list to be.
Ygg2
9 months ago
> Rust isn't as nice of community as people think
It's a numbers game. As the number of people using Rust grows, so does the number of Jerks using Rust. And it's not like the Rust community is a stranger to bullying maintainers of crates for various things.
> Async is problematic: Async Rust really is fine.
It's... OK. It has a few issues, that hopefully will get fixed, like making Pin from a generic struct into a type of reference. e.g. instead of `Pin<&str>` you would write `&pin str`.
There is also the coloring problem which is quite a hassle and people are looking into possible solutions.
johnnyanmac
9 months ago
>it would be really annoying to write Rust if you had to call `.copy()` on every bool/int/char. A language like this exists, I'm sure, but this hasn't stopped Rust from taking off
Well C++ does the same by default. You need to opt in for deep copies. C++ doesn't drop by default but modern practices like Smart pointers do.
>I'm unsure why this article is so upvoted given how vapid the content is, but it does have a snappy title, I guess.
Even HN isn't immune to the 90-9-1 rule.
kedarkhand
9 months ago
What is the 90-9-1 rule?
spease
9 months ago
I’m guessing 90% don’t care, 9% vote, 1% comment?
throwawaymaths
9 months ago
I've seen a case where the rust panic handler is used in FFI and this creates a memory leak.
seethishat
9 months ago
"There are only two kinds of languages: the ones people complain about and the ones nobody uses." This is a famous quote from Bjarne Stroustrup in defense of C++. Source: https://www.stroustrup.com/quotes.html
IMO, it's ironic to see Rust proponents using his quote in defense of Rust (and not crediting him).
csomar
9 months ago
I was going to write a rebuttal but then I read your comment and it mirrored roughly what I was going to write.
> - Rust inserts Copy, Drop, Deref for you: it would be really annoying to write Rust if you had to call `.copy()` on every bool/int/char. A language like this exists, I'm sure, but this hasn't stopped Rust from taking off
One improvement here could be the IDE. I don't want to write `let s: String` every time but the IDE (neovim LSP) does show it. It'd be good if I can get the full signature too.
> Async is problematic
Async Rust is by far the best Async out there. Now when I use other languages I am essentially wondering what the hell is going on there. Is there an executor? Is there a separate thread for this? How/When is this getting executed? Async Rust doesn't execute anything and as a result you can get an idea of how the flow of your program goes (as well as pick an executor of your choice, might not seem important if you are on the Tokio bandwagon but if you are in an envrionment where you need a custom executor and you need to control CPU threads, Rust Async suddenly makes a lot of sense)
pclmulqdq
9 months ago
> Rust has panics, and this is bad: ...okay? Nobody is writing panic handling code, it's not a form of error handling
As far as I know, the issue with the panics is that things panic a lot. Times when C or C++ will limp along in a degraded state and log something for you to look at will cause your Rust program to crash. That turns things that are not problems into things that are problems.
morning-coffee
9 months ago
First, things don't panic a lot in my experience writing Rust for the past three years. Second, when things do panic, it indicates a defect in the code that needs to be fixed. Aborting the program with a stack dump is the perfect behavior for seeing the state and the invariant that was violated and then figuring out the fix. Contrast this to C or C++ "limping along", usually until a later invariant causes a crash and being further away from and obscuring the true root cause, and we see why C and C++ code is generally still so bug-ridden relatively speaking. Fail-fast is not just a buzz word and program bugs are not recoverable errors. See https://joeduffyblog.com/2016/02/07/the-error-model/
pclmulqdq
9 months ago
These arguments get said a lot and they are all fine in theory, but in practice, all code over a certain size has a tremendous number of latent bugs, even Rust code. At a certain scale, you are virtually guaranteed to be running in a degraded mode of some kind. If the consequences of those latent bugs are operational nightmares, that's a problem. Most people would rather be able to roll in at 10 am to debug a minor issue from logs and traces than get a page at 1 am with 1000 stack traces in it.
jamincan
9 months ago
> These arguments get said a lot and they are all fine in theory, but in practice, all code over a certain size has a tremendous number of latent bugs, even Rust code.
Are you claiming this from direct experience, or do you have some data to back it up? Apparently the rollback rate for Rust code in Android is less than half that of C++. [1]
1. https://security.googleblog.com/2024/09/eliminating-memory-s...
SkiFire13
9 months ago
I wonder how you could realistically end up in those two situations for the same issue though.
morning-coffee
9 months ago
If your goal is to converge on correctly functioning software, you know, for the benefit of the users of it, then fail-fast can help. If your goal is to optimize the sleep patterns of devops people and make changes to code without testing before releasing it to production, yeah... do what you need to do. :)
pclmulqdq
9 months ago
You can have correctly-functioning software when parts of it are operating in a weird way. The complaint I have heard about Rust crashes is that the default behavior is to crash in any situation that could possibly be weird.
By the way, the trade you're talking about is great for desktop software (especially for browsers), but server-side software at scale is a bit different.
The borrow checker and all the Rust safety stuff is also completely orthogonal to most forms of testing. You don't get to do any less because your language protects you against a specific class of memory-related errors.
spease
9 months ago
Things should not panic a lot, and when I’m going over someone else’s Rust code I will discourage them to use panic at all if it’s socially appropriate.
Inasmuch as I am aware, the correct usage of panic is “there is no way to recover from this without leaving the application in an undefined state”.
Not “a file I expected to exist wasn’t there” or “the user gave bad input” or “I didn’t implement this feature yet”.
But more like “a cosmic ray must have struck the machine or something, because this ought to be logically impossible.”
Or pretty much, if you literally don’t see a mechanism in Rust that can pass an error upwards and the program also cannot continue execution without the result being affected, then you panic.
That’s a little stricter than what I understand the official guidance is, but not much.
If you have something panicking it should be less “I can’t see what’s going on” and more “thank god it stopped itself so it didn’t write bogus data to production.”
beeflet
9 months ago
>Rust inserts Copy, Drop, Deref for you: it would be really annoying to write Rust if you had to call `.copy()` on every bool/int/char. A language like this exists, I'm sure, but this hasn't stopped Rust from taking off
Is it possible to disable this behavior? I think it might be useful as a learning tool to familiarize myself with the Traits.
steveklabnik
9 months ago
It is not.
pjmlp
9 months ago
Maybe I suffer from brain damage due to knowing C++ since 1993, starting with Turbo C++ 1.0 for MS-DOS, however Rust is indeed getting into C++'s complexity.
Lets not forget people tend to compare 40 year old language complexity, ampered by backwards compatibility and large scale industry deployment, with one that is around 10 years old, with lots of features still only available on nightly.
The Unstable Book has an endless list of features that might land on Rust.
CryZe
9 months ago
Only about 1/3 of those are language features. Out of those a ton are #[cfg] related (i.e. being able to more accurately doing conditional compilation), const (lifting limitations with compile time evaluation), documentation, architecture specific additions (like intrinsics) and co.
I only see about like 30 or so that are actual proper language additions, some of which are just exploration without even an RFC either, leaving us with about 15 or so, which really isn't that bad.
pjmlp
9 months ago
Every single of them needs brain space, regardless of the use.
Also any language designer knows that every feature has exponential capacity due to the way it interacts with everything already in use, that is why innovation tokens are a thing in language design.
spease
9 months ago
I’ll try to keep this comment shorter. :)
The thing about Rust abstractions is that they’re a lot more useful and forgiving than C++.
Eg: In Rust, I cannot accidentally use an option incorrectly and have the program compile. When it fails to compile, there’s a good chance the compiler will suggest how I could do what I wanted to do.
In C++, if I dereference an optional without checking it, I’ve triggered “undefined behavior”. The program will probably just segfault, but it could also return a bogus object of uninitialized memory, but technically it could overwrite my boot sector or call a SWAT team to raid my house, and still be in compliance with the C++ spec.
Thus when considering code written in Rust, I mostly need to just consider the happy path. With C++ I need to pedantically check that they used the constructs correctly, and consider many more runtime paths due to how lax the language is.
If I see someone dereference an optional without an if-guard, I now need to backtrack through the logic of that entire function to make sure the program doesn’t crash. If I see someone use a destructured value from an Option in Rust, I can rest easy that unless they used unwrap() somewhere, the compiler has done that for me.
This scales well for larger abstractions, because if I’m not actively digging into some code I can treat it more as a black box where it interacts with the code I am working with, than as a box of firecrackers that might explode if I do something unexpected with it.
pjmlp
9 months ago
Use the C++ clippy version, plenty of variants to chose from.
Which by way is a good point, even Rust needs its clippy, so not everything is so perfectly designed to make clippy superfluous.
spease
9 months ago
> plenty of variants
Aaaand you’ve lost me.
I don’t want to waste my time either setting up multiple linters or having to drill down into the pros and cons of each. If the C++ community cannot even reach a consensus on which linter it endorses, I imagine it can’t reach a consensus on what it lints, which involves even more decisions.
Secondly, both times I’ve tried to roll out or use a linter, I’ve encountered passive or active resistance from the other developers on the team.
This resistance went deeper than the linter. On one team they didn’t want to use new language constructs from the last decade, on the other team they explicitly complained about me doing things differently than 15 years ago. In both cases they rejected what I understood to be the core C++ guidelines in favor of writing their own codebase-specific coding guidelines so they could pick and choose the constructs they understood rather than trying to adhere to what might be idiomatic for a particular edition.
Unless something is 100% endorsed by the C++ community, it’s absolutely not something that I’m even going to try to champion. I’ve already been flat-out told “no one cares about your opinion” trying to explain how type-safety in C++ can improve readability in code reviews, which I thought was completely noncontroversial.
To your second point, the point of linters is to guide code to be more idiomatic; it’s not an issue of language design, but of educating humans in mostly non-functional readability and best practices.
spease
9 months ago
Rust is nowhere near C++’s complexity.
And most of C++’s language complexity doesn’t come from “large scale industry deployment”, it comes from implementing a feature in a half-assed way, then updating it, but then the old feature needs to be kept around so all the libraries need to deal with two ways of doing things. Then something new and better comes along, and it needs to deal with three ways of doing things.
Meanwhile, developers get frustrated with how difficult the abstractions are to use, and end up carving out their own codebase-specific coding standards.
On Rust’s side, there’s 10x the emphasis on making things easy to use, so developers converge to consensus on pretty much the same modern style.
Just look at project management. Before I even write a project, with C++ I’m hit with choosing between a barrage of build systems and package managers, none of them particularly good. Will I use cmake and Conan? Then I’m stuck writing several lines of boilerplate before I even get started in a weird non-imperative language.
In Rust, I type cargo init and I’m ready to go.
C++ has basically completely fallen down when it comes to language design, and from what I’ve seen, is simultaneously in denial that things are so horrible for its end users (Bjarne Stroustrup iirc putting out an essay where he claimed “C++ is fine for any project I’m concerned about”) and suddenly trying to rush to (badly) copy features from Rust, and only recently coming to the realization that it really needs to abandon some of its fundamental precepts to stop self-sabotaging by carrying around massive amounts of baggage that nobody should be using anymore.
Meanwhile even the White House and other government agencies are saying “please use anything but C or C++”. Because ultimately, no one writes anything close to modern C++, and even modern C++’s memory safety guarantees are painfully minimal in exchange for massive amounts of code complexity (you still have to track every pointer lifetime yourself, and every safety abstraction is opt-in, so you still have to have the expertise to not cut yourself, and every codebase is unique and different in its conventions, which precludes running any kind of static analysis that could rival Rust without significant time investment).
It’s just..really bad. The only way Rust will get there is if it falls prey to the same feature hoarding as C++
But Rust already has a deprecation-and-removal process for features, as well as an edition system to provide backwards compatibility for old code, and standardized tooling for linting that’s 10x better at telling you how to refactor than anything I’ve seen with C++.
And god help you if you have an error in your code, because the C++ compiler will probably dump you out with a dozen irrelevant errors of dense template code you need to skip over, while with Rust you’ll make a mistake with lifetimes that will generate a text visualization of what you did wrong with the compiler pointing to what you need to change. Plus the Rust program will probably just run the first or second try, whereas the C++ program will segfault for the next ten minutes or so, because all the strictness in Rust means the complexity is more meaningful and less performative.
Look at what people are learning in schools today and I bet they’re still starting with new and delete or even malloc and free rather than things like std::make_unique and std::span.
The whole C++ ecosystem is basically predicated on nearly everyone having incomplete knowledge and doing something different and having to support or account for infinite combinations of features, whereas Rust has a higher barrier to entry but you can presume that pretty much everybody is using an idiomatic set of constructs for a given edition.
Anyway, sorry for beating that over your head. I started with C++ around the time of Visual C++ 6, and to me it’s absolutely shameful at how bad the language has gotten. Whole ecosystems (C#, Java) and subsequent ecosystems (Go, Rust) have arisen in response to how bad people have it programming in C++, and despite two decades of people running away from C++ to create their own general-purpose programming language, so many proponents of the language seem to still be in denial. They’ve simply shifted the goalposts from C++ being the general-purpose programming language to it being a “systems” language to rationalize why the vast majority of developers don’t use it anymore because it refused to evolve.
I see people these days comparing it to COBOL, that is, it’s not that anyone wants to use it for the merits of its language design, it simply has incumbency status that means it will be around for a long time.
pjmlp
9 months ago
Editions only cover syntax changes, and are hardly any different from compiler language switches when semantic and standard library changes are part of the picture.
Lets see how complex Rust turns out to be, if it is still around after 30 years, to actually have fair comparison.
We can also compare Rust in 2024, with the equivalent C++ version at 10 years old, when C++98 was still around the corner, C++ARM was the actual reference, and in that case the complexity fairs pretty equal across both languages.
As for safety, as someone that is a hardcover believer in systems programming languages with automatic resource management, I would rather see C++ folks embrace security than rewrite the world from scratch.
After all, Rust is in no rush to drop the hard dependency on LLVM and GCC infrastructure.
spease
9 months ago
The big difference (inasmuch as I am aware) is in source compatibility in practice.
If I use a header file, as any pre-C++-20 library will (have the major compilers implemented modules yet?), I am SOL. I am specifying a text-import of that library’s code into my code. You’d need an “extern C++11”.
As for comparing them at 10 years old, apparent language size might be similar, but in terms of program complexity C++ would be DOA.
You’re telling me it takes an equal amount of time to learn these languages, but with Rust I can write code that works on the first try, while with C++ I have to account for data races and memory mistakes at every level of my program? Why do I, a 90s programmer dealing with OSes without process separation and soon the dotcom boom, want to touch that with a 10-foot pole?
Java and C# would not exist. There’d be far too little value proposition with an alternative to C++’s memory-unsafety to justify the development of a whole new language.
You’d probably see the equivalent of Python and JavaScript (probably named RustScript following the logic of the time). There’d probably be a Go equivalent developed, ie “language that compiles fast and runs almost as fast as Rust that stresses language simplicity”. Language expressiveness and simplicity are at odds with each other and there are uses of both.
To be fair, Rust was developed with the last 30 years of programming in mind. But the thing is, memory safety kept on being a central issue of the languages that followed.
The next big design issue will probably have more to do with people trying to use LLMs as a first-class programming language. Eg something that’s easy for LLMs to write and humans to read.
Or something to do with heterogenous computing resources all sharing the same “program”. However here Rust seems already positioned to do well with its compile-time tracking of asynchronous resource dependencies between threads of computation, and procedural macros that can invoke an external compiler.
So I’m not sure that conventional language design is going to change the path it’s been on for the last 30 years until the human side of that interface starts to significantly change.
Most of the language design considerations we’re discussing boil down to “make things manageable to humans with limited memory”. If cybernetic augmentation or bioengineering sharply expands those limits, I suppose it could change the direction. Otherwise it feels like things are going to naturally cluster around “complex correct thing” and “simple iterable thing” because those are the two strategies humans can use to deal with complexity beyond the scope they can keep in their head at once.
api
9 months ago
IMHO the biggest Rust async annoyance is exactly this:
> Tokio's default choice of making `spawn` take Send/Sync futures
... combined with lack of structured concurrency.
This means async tasks look like threads in every respect, causing you to end up using Arc<> and other concurrency constructs all over the place where they ought not be necessary. This harms efficiency and adds verbosity.
khuey
9 months ago
It's not too hard to do tokio without Send/Sync futures. See the example in https://docs.rs/tokio/latest/tokio/task/struct.LocalSet.html... It's kind of annoying that the current_thread flavor of the executor doesn't automatically enter a LocalSet and make spawn_local work out of the box but it's easy enough to do at the beginning of your program.
jyafffyasdfs
9 months ago
I use Box::leak without shame.
api
9 months ago
I just coined a term for this: CRust. This is when your entire program is in unsafe {}.
lovethevoid
9 months ago
This was an oddly defensive and vapid comment. Mostly just handwaving away any views the article brings up, of which at least the article expands on their thoughts. This comment is just "meh not a bad thing" repeatedly. Why is this comment being upvoted?
jkelleyrtp
9 months ago
The title is inflammatory and yet there are few nuanced takes in the article. It's weird to see it shoot to the top of HN.
I think the loglog article is a much better, nuanced, full critique of Rust.
https://loglog.games/blog/leaving-rust-gamedev/
The internet is just so full of negativity these days. People upvote titles but don't read articles. Reading about people's views on subjects is useful, but I don't think this one is.
Shatnerz
9 months ago
Inflammatory? "My Negative Views on X" is pretty far from inflammatory. It is exactly what the post was, with some positivity sprinkled in as well.
northhanover
9 months ago
It’s 2024. If I read some thing I don’t agree with on the internet it IS inflammatory.
pessimizer
9 months ago
> This was an oddly defensive and vapid comment.
Even comparatively, next to your own comment? I have no specific idea of what you object to or why, but I have learned that you are upset.