Hacker News new | past | comments | ask | show | jobs | submit login
Why Not Rust? (2020) (matklad.github.io)
235 points by spekcular on Dec 18, 2021 | hide | past | favorite | 269 comments



I wish there was more stuff like this out there about rust, something, anything to counter what feels like blind optimism and fanboy-ism for the language. For me its hard to get a good sense of the language being worth it. People really do hype it up, but i do know there are valid criticisms out there. IDK if they're all blog writers. My own recent experience trying to write a server kind of left me unsure about how practical using the language is after being pretty excited about it.

I think the author wrote off "dependencies" to quickly. I'm kind of unsure about the state of dependencies. A lot of libraries seem to be peoples hobby/free time projects. I ran into strange comments in libraries where people don't actually seem to understand the domain they're writing the library in. Like I think all of the http frameworks are pet projects?

My feeling after using rust and async was that it kind of tricks you into writing sub optimal code often. Like what could be solved with a singleton ends up needing a lot of boilerplate, new data structures, complex code so you end up writing in some other way, or burning your self with mutex.(aside note, everybody recommending a faster mutex that's not in the stdlibrary seems odd). I also dont know why npm and node get so much shit for needing so many libraries but rust and cargo get a pass for these small libraries everywhere.


> I wish there was more stuff like this out there about rust, something, anything to counter what feels like blind optimism and fanboy-ism for the language.

I use Rust and I also use C/C++ and other languages as appropriate for each situation.

The fanboyism is a huge turnoff for me, too. But the anti-Rust complaints are also getting old.

Really, I’m just getting tired of everything in software engineering being turned into a competition, as if we’re cheering for our chosen sports team and we can’t stand to see the other team win anything. So much online discussion is wasted on Intel vs AMD, Mac vs Linux vs Windows, Rust vs C/C++/Go, React vs Remix vs 10 other frameworks.

It’s getting really hard to extract actual useful info from these permanent debates when the fanboys from different sides pour in to compete.

The best resources I’ve found are from people who aren’t afraid to use multiple platforms and acknowledge that they all have pros and cons. If someone can’t describe something in terms of tradeoffs, they’re probably not trying to make an honest evaluation.


Very much agreed. It's not like the anti-Rust comments are much better. They're often quite biased in the other direction and rest upon arguments that boil down to "if you write C++ correctly, it's a very good language". But of course, Rust has flaws and design decisions that make it a poor fit for many people/usecases. Really I'd love it if people kept an open mind, did their research and tried to not let their biases rule their judgement.


All those arguments, as usual, also fail to discuss the existing ecosystems.

Sure one can somehow write Rust-CUDA but is going to have an uphill fight versus someone just crusing along focused on the actual problem, instead of building infrastructure.

That is just one example.


What weirds me out is to see your comment grayed out within minutes of posting. Have an upvote, it's a valid point you are making.


I survived USENET and Slashdot, and am the first generation out of a 40 years dictatorship, downvotes on Internet forums don't bother me.

Thanks for the upvote anyway.


Oh yeah that's a valid criticism. Same reason why I don't plan on writing a CRUD API in Rust. It's an uphill slog compared to Rails or Node.


I thought that's the one part that had a bunch of frameworks already made


I still learn a bit from those sorts of debates. But for me they're meaningless because what I need from a language has nothing to do with nerd debate hour. I need a job, so it has to be out there, not just in my city but small cities in case I move. Next I care about good tooling. Otherwise the only debate I feel strongly enough is static vs dynamic typing, and that's mostly because I don't think I'm a good enough programmer to build a 500KLOC+ application without compile time type guarantees. Give me a language with the above 3 things and I think we have a deal, and all of them are about making my life easier.


Most languages and ecosystems greatly benefit from network effects, I don't know how that will ever be different.


> It’s getting really hard to extract actual useful info

The info is still there, you just need to use a different extraction technique.


Even so, “if a text wants to be understood, someone has to do the work, either the author or the reader”. Putting all the work on the reader is a turn-off.


I love using Rust, but I also get a bit annoyed by the hype. It's absolutely true, for example, that there are highly useful programming patterns that are extremely difficult to express without tools like garbage collection -- including many classical ideas from functional programming. But Rust users sometimes give you the impression that wanting to write any code which doesn't fit the specific shape the borrow checker expects is morally wrong.


Does using Rc or Arc feel morally wrong?

Having shared mutable state, or doing bare pointer arithmetics is "morally wrong" in the sense that it's a constant source of bugs in production, sometimes dangerous. Any language that reminds you about that is doing a useful thing; C++ is very much capable of that, too.


Meh, bare pointer arithmetic (and shared mutability, for that matter) can be quite morally OK if it's properly isolated to a self-contained module, with detailed specifications on its behavior. That's why Rust has an `unsafe` facility. It's morally wrong to use it across modules (because it's obviously non-compositional), but that's not what Rust devs are doing. This is not C/C++.


And good OOP is exactly about encapsulating that mutable part.


It's a bit silly to say shared mutable state is morally wrong. Rust programs have shared mutable state in that indices often refer to mutable data, and Java programs allow more conventional shared mutability without memory unsafety.

Shared mutability can enable some bugs, like the existence of a CPU enables bugs, but that doesn't mean CPUs are morally wrong.


Raw shared mutability is a mine field the moment mutations that depend on the current state occur.

If incrementing doesn't always increment you are in for a bad time after all.

You are always going to have data that is shared and changes. Any non trivial system will. Rust just discourages the naive "just point to the heap" method that tends to work until it doesn't.


Except Rust can only help when the heap being pointed to isn't shared across processes, possiblity written in multiple languages, e.g. NUMA shared memory.


If you do a crazy enough thing it will break isn't material to my statement "naively accessing the heap as if that is thread safe is bad anyway".


>is morally wrong

That is the problem not just with Rust but with today's tech. There is moral story or ideology everywhere. My definition of "engineers" is basically trade offs. Unfortunately that doesn't seems to happen much in software. The Rust Evangelism Strike Force.


Huh? "Morally" here is just shorthand for "practically, as a rule of thumb, for most intents and purposes" - it is the opposite of "morally correct". There are solid technical reasons for these concerns although they're a bit tedious to describe in detail (which is why we resort to these rules of thumb); they're not arbitrary or "ideological".


>Huh? "Morally" here is just shorthand for "practically, as a rule of thumb, for most intents and purposes"

There was an era when any rust code that use Unsafe is considered "morally wrong" regardless of whatever technical reasons or personal preference.


The brouhaha about Rust Unsafe was about code that used it where it was not needed (because you could write safe code that would optimize to the same thing), or used it incorrectly (not marking code that was only conditionally "safe", thus exporting unsafety to "safe" code potentially across Rust modularity boundaries.) And the actual issues got resolved rather quickly.


This is my largest issue with Rust right now too. I’m happy to use it for personal projects on my own computer, but I don’t feel comfortable shipping a huge pile of code I don’t really understand onto someone else’s computer. I trust a self-contained standard library (like those distributed with Go and Python) much more than a patchwork of packages that depend on other packages, written by many different people, and which may be in different states of maintained, unmaintained, have security holes… putting my name on software based on these packages means taking responsibility for all that mess.


> shipping a huge pile of code I don’t really understand

Isn't this right for any language, though?


Yes. One glance at Log4j fiasco shows no one really understood all of the code.


Log4j is not a standard library, it is just very popular, and it proves the original concern. It is treated as standard but it is not, and package muddle the waters even more. Remember leftPad.

The lack of a stable ABI is also a problem. For example, on my Linux distro, if a library has a bug, I just update the library and all software using it are fixed. No need to recompile everything.

So, essentially, the cargo system makes it easy to import weak code and hard to fix it later.

I am not saying that cargo is terrible, but it is a problem with rust that is not to be dismissed.


It still doesn't negate my point.

You need to rely on other people's code. Whether it std lib or not. Left pad is because of:

A) ease of modularization

B) problems with tree shaking

C) people want small easily understandable library

Which tbh works more often than not.

----

Stable ABI is a curse as much as blessing. Once you have stable ABI, you will never want to break it. Even if breaking ABI would be beneficial long term. See

https://cor3ntin.github.io/posts/abi/

And if you desire Stable ABI there is option of exposing C API in Rust.

----

> So, essentially, the cargo system makes it easy to import weak code and hard to fix it later.

Hard for who? Cargo can easily fork a package and recompile it. It makes it harder for distros. But you can ship static linked dependencies, easily.


All valid concerns -- but you have to worry about bringing in other code in your supply chain in almost any language, unless you are always doing everything from scratch!

Thank goodness cargo audit (for https://crates.io/crates/cargo-audit) in any case.


You’ll find that a lot of software that runs large, enterprise applications is comprised of “pet projects.” Node.js and Python both started as pet projects.

If your criticism is that there isn’t a lot of maturity in the ecosystem, then I would agree. The author also makes this point.

There will always be something the industry is excited about. Rust will eventually find its place and its hype will be eclipsed by whatever new trend/language is cool 4-7 years from now.


If you come at it from c/c++ systems programming and you never even had a decent package management story then of course Rust will be a blessing.

Those that will be confused and wonder what the hell it’s about is those who come from node/go/Java and think that using http is a “hello world” example of what Rust should do with ease.

> I also dont know why npm and node get so much shit for needing so many libraries but rust and cargo get a pass for these small libraries everywhere.

I think one big difference is the less promiscuous (but more frustrating) dependency management. In node I end up with 15 versions of a popular “should have been stdlib” library. In Rust you usually just have to allow one. So the libraries that form core functionality tend to be conservative about changes and get absorbed into std.

Js obviously doesn’t add things to the core platform very quickly.


Why not write a singleton in rust? You can write a lazy global for that. The language does not prevent you from writing anything sane


The state of the ecosystem is concerning, but natural. It always takes some time until the best/standard libraries become visible amongst the noise. Lastly, I was looking for Parser combinators and the first three hits and no commits for years. That's definitely a red flag for me.


What did you get stuck on?

> I also dont know why npm and node get so much shit for needing so many libraries but rust and cargo get a pass for these small libraries everywhere.

Because cargo is a better package manager in every aspect.


> Because cargo is a better package manager in every aspect.

It is not. For example, cargo doesn't have namespacing, which makes the issue of name squatting worse. I'd like to have every crate of the tokio-rs organization on Github (https://github.com/tokio-rs) under a @tokio/ namespace or something like that. npm allows that.

Dismissive responses like that are part of why people talk about "blind optimism and fanboy-ism".


I'd love to see that happen, but as I understand it, that's a decision for the crates.io registry. Cargo itself doesn't deal with those types of details and you could host a custom registry that does have namespaces.


You are confusing cargo and crates. Also this was a conscious decision.


> Because cargo is a better package manager in every aspect.

A piece of software can only help with some of the less important questions when you're working with many dependencies.


It handles the insanely tedious parts of package management like version mismatch.


It doesn't handle the issue that every tiny piece of functionality is a crate, because everyone wants to have one on their CV.

Also there are no namespaces and integration with other languages boils down to writing our own build.rs scripts.


I'm no node developer, but even with ~100 packages in a Python project it was really rare to see "version mismatch problems". There's probably a lot of talk about it because "just install newest spec'd version recursively" is not technically correct and can violate package version constraints, and it's also probably the only algorithmic thing you can put in a package manager, and optimal solutions are of course NP-hard, making it an interesting thing to work on. But practical impact? Far down the list.


I literally just downloaded a Python program that didn't run because I had the wrong version

In Rust, when you compile an earlier edition with the newer compiler it actually works


I have definitely run into these problem with much smaller projects in both python and js.


Because Rust is a `cargo` cult. /s


[Ice Cube voice]: Started off with too much cargo, dropped 4 letters now I'm making all the dough.


The "dependencies" can be written off quickly as the "complaints" about them are ridiculous.


There's a statement that Rust is a systems programming language, but that in most cases one doesn't need this, and that Go or Kotlin are thus in most cases better alternatives.

This image of Rust as lower level than Go isn't one I agree with, but I can certainly see how people end up there. Go has it's garbage collector and userspace threading model, one gives up a lot of control to a runtime that you don't have to in Rust.

But as the author mentions if we're after good enough speed these details aren't important. So I don't most of the time care if there's a GC or not.

What I care about is the code I have to write, and Rust IMHO offers me nicer abstractions and more features.

The Go world in their desire for simplicity, use a for loop for everything, but in Rust we have the excellent iterator trait. The Go world offers me product types, the Rust world offers product and sum types. The Go world offers some mechanisms for codegen, but it is a far cry from Rust's macros.

Go I consider a modernized C, that is notable more for what you can't do than what you can, and how fast it can be learned - owing to a minimal and already familiar feature set.

I confess that I have a bit of a chip on my shoulder, I have for the last few years been working as a Go developer and in the last few months it's started really started to grate me how much work things are. I really miss things like '#[derive(...)]'.


Go, like Java, was designed by people who intended never to write any code in the language, themselves. Both are languages which those individuals designed for use by people less intelligent, careful, and thoughtful than themselves.

The case of Java demonstrates they were mistaken: their estimation of their own understanding was grossly outsized. I don't know enough about Go to say whether that is true of Go's designers.


I am not sure why you're being downvoted, you're right. Here's the quote from Rob Pike I find astounding:

"The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt. – Rob Pike" [1] (emphasis mine)

You and I: we're not smart enough to use modern language features. And it just so happens that the language features and practices that we can handle are the ones that Rob Pike likes and settled on as good in the 70s and 80s. Anything from the last 25 years, we're not capable of understanding.

Honestly, part of many bonuses of leaving Google at the end of the month (after 10 years there) is that I hopefully will have the choice not to use Go and its heaps of insulting boilerplate... but I also hopefully won't have to deal with that kind of arrogance.

[1] http://nomad.uk.net/articles/why-gos-design-is-a-disservice-...


Researchers tend to write pretty poor code, if any of the research papers I've read/read corresponding code for are any indication.

Obviously not trying to state anything deep here by over-analyzing that one point in his quote, but kinda funny his statement implies researchers write decent code.

Often I question the result of a paper due to how bad the code is. Many paper results cannot even be replicated by writing your own code following the papers description.

I agree more fundamentally with the fact that most people write low quality code if there aren't structures/patterns already in place to protect them from themselves. From that perspective, I agree with his point. Though I'm not a big fan of the implementation of the idea


Welcome to the Xoogler club :D. Just curious what areas did you work in, generally speaking? I never saw a line of Go in close to three years working around the Ads products.

Obviously it's a massive company and I saw maybe 5% of it, but I joke with my friends that I had to leave goog to get real exposure to Go and borg/k8s.


I've been through all sorts of PAs (including ads in my first two years). And yes, I only really saw Go in my last year here, working in Core. I transferred from Nest/Hardware because WFH was too difficult for that kind of work (hardware devices), and I wanted to get back into Google3 so I could be more productive. And it so happened the codebase I landed in was Go. I mean, it's been mostly tolerable, but it's also just... not good honestly.

And yes, I do think generally Go is used more outside Google than it is inside. It's not a language made for Google -- despite what Pike is saying -- it's a language made by some people who happen to work at Google to scratch an itch they've had since they worked at Bell Labs.


In Romania there's an old question to find the character of somebody: are you Roman or Greek? Because if you are Roman, you put practice above theory, you are a pragmatist, skeptic, if you are Greek you will put theory above practice, you are an idealist, optimist, at the expense of hardships in the material world and other potential drawbacks. Rob Pike chose Roman, otherwise it would have cost Google money to train those people and we don't know if those language features could bring any benefits for the kind of software they develop. As he said, they are not researchers working with category theory, instead they program ever-changing software for an imperfect world driven by profits, rather than academic idealism.


I mean, I actually work(ed) at Google and this is nonsense for Google developers.

The most used and deployed code at Google is written in C++, not Java or Python, and while we have a sane subset of it in our style guide it is by no means dumbed down to the level that Pike seems to imply we need it to be.

Google has done fairly fine deploying C++ into production for a couple decades. I haven't found Go superior at all so far, more insulting than anything. And tedious and opinionated in all the wrong ways.


I just replied to your other comment further up thread, but yes this is my anecdotal experience as well. You couldn't walk ten feet without tripping over C++ and Java. Never myself saw Go checked into corp.


Seems Go insulted you so much that you really lost sense of proportion or any reasonableness in your comments.


I never had that, so we can't blame Go.


”Pragmatism vs Idealism” is pretty much like saying “we're doing the right things and others are wrong”. No software engineer would define themself as an “idealist who don't take reality into account into their design”.

For instance, I'd consider Go being very “idealistic” since it was designed mostly from the vision of a small group of people with a clear mantra: “simplicity”. But of course, Rob Pike would never have advertised his language this way.

On the other hand, one could argue that Rust is pretty much is the “realist” camp, since it was initially designed in a very different shape from what it later became when early adopters started using it (the Servo team at Mozilla in the beginning, and then other groups: for instance the Fushia team at google at an impact on the design of the async part of the language).


Curious: Did 'Commander Pike' influence choice of 'Comrade Porcupine'?


No I've had this nick and various variations on it since I was a teenager on LambdaMOO in the early 90s, and I don't think I was conscious of Commander Pike.


You sound like you have a chip on your shoulder and you come off as a spoiled child. Just as the anti-Trump crowd doesn't like Trump's personality, you reject Pike for his arrogance.

He's done great things. Think about the caliber of people that man worked with every day. And then he goes to Google and sees thousands of 'ordinary' people slinging C++ and doing web work. We become products of our environment. There's a lot of gap between him and you. And that's ok. You'll go on to do another 10 years at another big tech company and live a good life.

I'm way below your caliber and I see some arrogance in your words. I think both of you are arrogant because you unconciously became a product of the environment. I'm just a nobody that fails 9/10 interviews, including Google 2 months ago. It takes luck for me to get hired anywhere and I find it hard to relate to the middle class people I work with because I've been so poor. But I bet you I come off as arrogant to tradesmen, cashiers, janitors, and many others. Just let it go.


> Think about the caliber of people that man worked with every day.

Greatness by association is not a solid concept. It shows how lucky a person is to be surrounded by great people but in itself does not count as an evidence of his greatness. But on the other hand, great research minds tend to cluster, thus his priors are above average.


> Just as the anti-Trump crowd doesn't like Trump's personality, you reject Pike for his arrogance.

This feels like an odd and unfair comparison.

I have nothing but respect for Pike and what he’s accomplished.

I don’t dislike him in some anti-cult-of-personality. I’m not ignoring good work he’s done just because it doesn’t fit my world view.

But I CAN criticize his individual work for being limiting or lacking ergonomics that I like.

And it’s entirely fair to look at Pike’s personal motivation for making the decisions he made, because it has an impact not only on what Go is currently, but also what it’s likely to be (or likely to not be) in the future.

If Go were created with the intention to be, say, a cleaner C++ with garbage collection, then I’d be all over it. I’d know that even if I don’t fully like it’s implementation today, it might eventually “get there”.

But instead it was created as an admittedly dumbed down language for people that Pike personally decided needed a dumbed down language, so I know that it’s never going to be what I want it to be.

That’s not an attack on Pike as a person. It’s not me blindly following a media campaign trying to destroy someone.

It’s me saying that I benefit greatly from generics and more robust error handling, and Go is not likely to have those in the capacity that I want because the whole motivation behind the language was to avoid those things at all costs.

None of which takes away from Pike’s career in its entirety.


Nah man, you are not below me. And those kind of comparisons are ridiculous in any case, which is why I reject the content and tone of Pike's quote there and also many of the value judgements about programmer's 'smarts" that seem to have gone into the development of Go itself. It's that kind of attitude that turns me off entirely (also Google's ridiculous interview process but that's another story).

I'm not sure if Pike himself holds these opinions, or if that quote was just a slip, but it's not nice. TLDR Pike is a 'great' man, with smarts well beyond me, but that's not of a lot of relevance to the code that we (code mechanics / producers) have to write every day, and I found Go tiring and insulting to work with.


Not only do I use D for all my programming now, I've also gone back and translated my older programs I still use into D.

Most recently I converted my ancient (1980s era) disassembler into D.


What are you talking about Java?

Gosling and others have written plenty of code in Java themselves, plenty of Solaris tooling was migrated to Java (a fact that Bryan Cantrill has complained often in his talks), and it replaced their OpenSTEP efforts, with Java EE being a rewrite from Distributed Objects Everywhere, originally written in Objective-C.


The Java authors were quite open about their absolute preference for Lisp, and their distaste for OO.

That Gosling did not fully understand features cribbed from other languages is evident from how broken the Java version of those features are.


Surprising opinion given that Java is heavily based on Objective-C.

https://cs.gmu.edu/~sean/stuff/java-objc.html

As for your reference to Guy Steel, he was just one person on a large team, which besides the point above was full of ex Smalltalk and SELF people as well.

Maybe learn properly about the Java history?


Go itself is a huge project written in Go. What are you talking about?


Famously, it even took many years for the compiler to be bootstrapped. That’s unusual in the extreme.


One thing that has been discovered over the past 50 years and applied over the last 30 or so is that writing a bootstrapping compiler for a young language tends to strongly bias the language towards being good at writing compilers (potentially to the detriment of other features). Compilers are essentially graph algorithms on loosely typed data. I think a lot of the reason it took so long for Rust and Julia to be invented is that they are both not very good languages for writing a compiler in, so in the era where all the new languages had bootstrapping compilers, no one would write a language with the sets of tradeoffs they have.


I very much agree. In fact, taking it a step further, OS which self-host development also have this problem where they over optimize for an OS good at compiling and not necessarily good at other things.


They had a functioning compiler and decided to concentrate on other areas and it's not too uncommon for a languages's compiler to NOT be written in that language. Afterall Rust relies on the non-Rust LLVM.


> Unusual in the extreme

The most popular python and ruby implementations are written in C, right?

Swift is written in C++

It seems not sooooo unusual.


Python and Ruby are not from the get-go compiled languages but interpreted ones.


Writing the compiler for your new language in it amounts to wankage, these days.

There was a time when doing that helped convince people the language could do practical things, and might be useful because you might not have had a compiler you liked for your dev environment. Nowadays, though, there is so much support for coding compilers in an existing langauge that building one in the immature language means wasting a lot of time, and furthermore makes your language hard to change because maybe the compiler is using something you want to change. There are more impressive things to write in your new language that might be actually useful.

Thus, rustc is (mostly) not coded in Rust. Rust's demonstrator project was the guts of a browser, instead. Notably, that project was coded in a language substantially different from Rust both today and at the time.


3 years is not that many years (Go is now 12 years old), and that's not unusual. There are other priorities when you have just released a new language.


Go is really just a modernized Alef/Limbo, and there's plenty of code written in those languages, in their own niches. It's quite a good language for what it's intended to do. (People sure love to talk about its lack of generics, but Java pre-1.4 or so didn't have generics either. It takes time to find out the best semantics and integrate them into the language.)


Pre-generic Java required (un)boxing and runtime casts everywhere, so it wasn’t really safer than a dynamic language, just far more tedious. I’m thankful that we pretty much burned that code to the ground and started over. Those casts are still in the bytecode for the verifier, but at least we no longer have to reread them, and we have warnings when we violate the assurances that they won’t fail.


> was designed by people who intended never to write any code in the language

That's false. All of the original developers started writing side projects in Go extremely early on and all of them still write tons of Go including on their side projects. They don't have their ego tied up in their choice of programming language.


Even if that were true, is it a bad thing?


I'd say that Go is mostly taking the place of PHP4 of old. Go is much less ceremony than C, thanks to built-in data structures and GC. If you want something to be built quickly, using only the simplest expressive means, and with very little ceremony around coding and deployment, Go is a clear choice. Much copy-pasting needed? Screw it, we have to ship tonight, and we will.

Rust is a clear replacement of C++, but with the flavor of OCaml and even Haskell added to it. It requires thoughtful planning, a good grasp of what you are building, how it should work, down to the lower levels, and significant knowledge of the CS fundamentals. Relatively few parts of the industry appreciate such an approach, but where it's needed and productive (see e.g. control software, system-level software, well, web browsers) it shines, and has no serious competition.

Possibly architectural progress in libraries will one day make writing web services in Rust ergonomic enough to compete with Typescript, much like auto-ptr / unique-ptr made writing C++ less painful.


Most of those domains have security standards, even when using Ada/SPARK or formal methods, so Rust still needs some work to get there.


I only partially agree with you. The examples you gave are solid, but there's a big elephant in the room: async programming. In Go async is transparent, in Rust async tends to be a huge pain. Preemptive multitasking really makes everything easier, and I would take it over Rust's type system and abstractions.

I'm personally patiently waiting for OCaml multicore, which should have the best from both worlds, except the large communities.


I think the JVM would also be a good choice once Loom lands. I've seen that right now the Java architects are trying to unify the ALGOL flavored Java with ML in the sense of algebraic data structures, pattern matching, local type inference. As you said, OCaml does not have a big community, library ecosystem. It also does not have the 100B$ garbage collectors of the JVM, which are a deal breaker, at least for me.


That's a good option too, though in that case the tradeoff is that compiling to a single binary is a bit harder than in the other languages. Someone mentionned Scala too, which is even "higher level" than OCaml, but I think Scala has the issue of future/async (monadic) concurrency, and is even harder to compile to native. There are lots of options in that space, which is great!

> It also does not have the 100B$ garbage collectors of the JVM, which are a deal breaker, at least for me.

Can you expand a bit on that? I was under the impression that even with all that investment, Java code tends to be slower and more memory hungry than equivalent Go code.


No amount of $ spent on JITs and garbage collection can solve the problem that Java was designed with no respect for memory use. It just doesn’t have the features (such as but not limited to value types) that let you save memory.

They’re adding value types of course, but I haven’t looked at how exactly they’ll work.


Go is better at keeping values on the stack. Java has better throughput when collecting objects that escaped to the heap.

Java also tries to optimize out method dispatch, so we can use it freely where Go might tend to avoid it.


There's more than just the stack/heap - in a compiled language your constant data is file backed and doesn't need to contribute to memory footprint at all. Java doesn't have that because jar files are missing it (being zipped, syntax that looks like it creates them emit heap allocation bytecode, etc.) and it doesn't have multidimensional arrays or things that might help you use it even if you wrote it in C.

There's some other tricks like tagged pointers, purgeable data it doesn't reliably have either.


Java NIO can mmap a file of bytes or ints or whatever without using the heap’s private pages, and there are some JVMs that persist and reuse jitted machine code.

I’ve read that games and simulators schedule realtime asset loading pretty carefully; what other problems are solved using large constant data?


ZIP does support uncompressed data, so this could easily be added in a backward-compatible way if deemed worthwhile.


Eh you can still have compression, what’s important is the OS pager knows how to read the page from disk as opposed to eagerly loading and swapping it.


Until Valhalla arrives, Unsafe package and JNI are options as well.

Or is it ok to use cgo to work around Go's shortcomings, but not JNI for Java's?


Sure it's fine, but isn't that not writing in Java?

I don't remember how good the Java interfaces look though, eg if you worked around no constant data by defining your arrays in C and passing them back, would they be bounds checked arrays?


Just like CGO is not Go, yet not a reason to throw everything away.

If one is dumb enough to use C style arrays instead of C++ bounded checked ones, yes that is a problem, again just like C arrays defined in CGO.


> If one is dumb enough to use C style arrays instead of C++ bounded checked ones, yes that is a problem, again just like C arrays defined in CGO.

I'm talking about defining a 'const int[]' in C and having it appear as an 'int[]' in Java. I think that's even less likely to happen if you define a const std::vector.

Actually I've never even seen someone define constant data in C++ using a vector, but this fits my experience of C++ developers telling me I'm stupid when I do the only thing I've ever seen anyone actually write.


What can I say, you hang around the wrong people.


> Can you expand a bit on that? I was under the impression that even with all that investment, Java code tends to be slower and more memory hungry than equivalent Go code.

Go doesn’t need a good GC as much because it can rely on value types sometimes. But for general enough workloads a superior GC can triumph.

Also, Java is memory hungry only in that doing GC when it is not absolutely needed is useless work. The JVM is actually quite power efficient due to trading off memory for better throughput — so especially in server environments with huge (up to multi-TB) memory which the JVM is free to use, it can be ridiculously fast. So no, java is not slower than equivalent Go program though correctly comparing languages is nigh impossible.


Does Java have sum types yet?


It does, through sealed classes.


Yes, personally I think C#/.NET is a much better complement to rust than golang is, but it’s just not as hip a langauge.


Except in that ecosystem Rust is no match for C++/CLI and C++/WinRT tooling.

Yes they are Windows only, but lets be honest most pure .NET shops aren't moving away from Windows, as .NET cross platform has left part of the commercial ecosystem behind and no one is willing to port those stacks into cross platform ones.


The author could have recommended Scala, which has all of Rust's type system benefits, plus garbage collection (and of course, minus the low level control over performance).

YMMV though, as everyone uses Scala differently. A lot of Scala code goes in a more abstract direction, but if you use it in a more imperative Kotlin-esque way it's a very nice language.


I am very nervous about Rust. My team recently started on a Rust project because we had a need to build something that would compile to WebAssembly. Without getting into too much detail, the WebAssembly runtimes for memory managed languages wouldn't work for what we're doing. We are not a company that does a lot with C/C++ and those of us who have used C/C++ do not particularly enjoy it, so we decided to go with Rust.

I do like Rust and it has worked well for this particular project. The problem, though, is that now there's a Rust mania that has set in and a desire to write/rewrite lots of stuff with Rust. Based on what I've seen out there on the web, this seems like a common thing. While Rust offered a clear benefit to us for the WebAssembly work, for every other case the benefits of Rust are mostly absent or minimal but the drawbacks around losing a garbage collector, losing a large healthy package ecosystem, losing use of our existing internal libraries and tooling, etc. loom large.

So I am in an unhappy position where I keep telling enthusiastic Rust advocates no. Another interesting thing is that people tell their friends that we are using Rust and now they want to apply to work for us. We have a hard time recruiting and there's part of me that wonders if we'd just be flooded with applicants if we started advertising Rust jobs. This is somewhat tempting - we might be able to easily hire teams of enthusiasts to churn out Rust but for how long? How long will it have this magic aura and following? I certainly don't want to be left with tons of crappy Rust code in a few years that nobody wants to maintain.

I feel like HN has mostly been very enthusiastic about Rust. A thread critical of Rust is rare and I feel like it is refreshing.


Wait, you're complaining that the people who used Rust to write a production software enjoyed it so much that they want that experience for all other softwares too? They enjoyed it so much that they told others? and others who also enjoy writing code in this language want to work for you? Are you saying you're afraid that "too much of a good thing" could cause issues for you?


I feel like I already articulated why I think Rust is not the best choice for most of what we do and you ignored it in order to write a snide response. Can we please keep HN from devolving into Twitter?


You didn't clarify what your existing stack/tooling is (other than it being based around a GC language), so it's kinda hard to give more detailed feedback. (In general, though, Rust tries its best to make GC-less development as productive as programming in ordinary GC languages, by generalizing the C++ 'RAII' pattern. Wrt. ecosystem concerns, Rust can interoperate with many existing languages though of course some will be harder than others, and interop with GC languages is quite challenging in general.)


> Rust tries its best to make GC-less development as productive as programming in ordinary GC languages

I think it is generally impossible. While first draft version of the program may have similar velocity, later maintaining will necessarily hit those leaked lower level detail which is simply not a problem with managed languages.

But I don’t think that this is a problem in any way or shape.


I’ve found Rust interaction with Go via `cgo` to be quite straightforward, fwiw. RPC approaches are also a popular option.


It looks like the team greatly enjoys using Rust, but it makes the process of writing the software slower, due to more time spent writing GC-less code, hunting for or writing missing libraries, etc. That is, velocity goes down, even if the probability of bugs and the enjoyment of the team both go up.


I didn't get that impression. Also when calculating velocity we really should include the time it takes to iron out bugs. Rust has a lot of features (sum types, pattern matching, etc) that result in your program being more likely to be correct, not just memory safe.


> too much of a good thing

= blind optimism.

When it comes to migration, optimism can be far far worse than pessimism. The hurdle for adoption is much higher for existing projects than new projects.


Or maybe if it ain't broke don't fix it. Why bother rewriting functioning systems in the language du jour?


I have the same opinion.

The best thing about rust is that rust attracts more people to learn systems programming languages. And thus, there will be more system programmers.

Nowadays, young people favor application programming far more than system programming.

But the problem is there are not that many system programming opportunities.

Then they decided to rewrite the existing systems with rust. We can find a lot of these examples on GitHub. Who knows if it is just a moment of enthusiasm, and how long will it last?


My hopes is that Rust will result in more user-facing applications being written with the light weight, responsiveness, and performance of low-level-optimized code (no GC pauses, less allocation churn, easy safe parallelization, no segfaults unlike C++). Applications used to be written in C (and even RollerCoaster Tycoon in assembly), and GC'd languages are easier to develop in but slower to run on the user's computer. I'm not sure how successful Rust will be, since it discourages using multiple ownership or refcounting, and doesn't supply garbage collection, in situations where it is the easiest way to reason about code. IMO this raises the bar and discourages even working in these domains. (In my experience gtk-rs is more frustrating and confusing to use than unsafe Qt in C++.) And given Rust's tendency for dependency bloat, the applications don't come out as small on-disk as possible.


We will probably see some support for "pluggable", localized GC in Rust once it gains proper support for arenas/local allocators. This should make it easier to use Rust in domains where GC is pretty much a requirement, such as computing with general graphs.

Executable bloat in Rust applications is generally due to a lack of "idiomatic" support for dynamic linking (.dll or .so objects). You're expected to pretty much write your own interface layers using the C ABI, and it's especially hard to make these "interface" layers play well with generic code, which is quite ubiquitous in Rust.


As someone who mostly enjoys cpp, for me the math just didn't seem worth it to really get fluent in rust. I agree there are less system jobs than app jobs kind of prima facie, but there's not exactly a lack of systems jobs for cpp programmers at the moment.


C and C++ are effectively immortal at this point. This is due to the fact that they've been king of the hill in systems for decades. Effectively the only choice for that domain. If you enjoy C++ more power to you. But there are those like myself who have experienced writing code in e.g. Python and Haskell and with those backgrounds find C and C++ especially unpalatable. This is part of why there's so much excitement for Rust - it has many of the features application programmers are used to (such as package management via Cargo) and is also proven capable of competing with C and C++. That's never happened before.


There is also another reason, domains where they are the only game in town, e.g. HPC, and any newcomer needs decades to get into the club.

As for not happening before, Delphi and Turbo/Object Pascal on the PC and Mac worlds beg to differ, unfortunately C++ adoption from the OS owners pushed them away.


> Who knows if it is just a moment of enthusiasm, and how long will it last?

This is one big problem for me, too. I don’t think those young kids have any clear idea on what they are doing. I’ve seen the same thing happening with Python in the past. Heck, I remember some kids who went far enough to use python as their default shell. Such enthusiasm, but pointless. It took almost 10 years since the beginning of the Python hype until it actually dethroned Java.

Same for Rust. It does have a fine edge - I’m tbh excited a little - but that’s just it. Rust taking over the world? It will only after people got tired of calling it cool.


I'm curious, what are the types of other things that you do and which people want to rewrite to Rust?

In general I'm very much against any rewrites without a clear list of things that are lacking in the current implementation, details on how the rewrite would address this and what are the functional requirements for the rewrite to succeed.

But regarding new projects I think that people sometimes underestimate Rust in non systems programming scenarios. Not saying that you do, but at my job there is the notion that Rust is only good for "close to the metal" performance and where usually C/C++ would have been used. I think this is a flawed view. So while I am aware Rust is not the best choice for some stuff, if I had to write a web service and/or microservice that's not rendering anything I would often choose Rust just because of all the correctness guarantees. I come from a Ruby background, but I've done a lot of other languages too and a confidence I have when writing Rust is a big factor on why I like the language so much. I'm not really sure what percentage of Rust devs work with web services, but I think in the next few years it will be a big percentage of work done in Rust.


Rewrites seem like a bad idea (unless you’re hitting performance issues), but maybe you could consider letting people start some new projects in Rust? It’s a pretty good fit for backend web dev if you do any of that.


Most of the "rewrite in rust" I've seen is for software that is in C/C++ so they aren't giving up a GC. That might just be the sorts of projects I follow though.


Yes, "let's rewrite it in Rust because we're tired of fixing buffer overruns, or memory leaks, or race conditions". This is very understandable, and mostly applies to systems software, slower-moving, high-reliability things.


As long as unsafe code blocks are validated in each crate release, e.g. race conditions in shmem/mmap.


The vast, vast majority of buffer overruns, memory leaks and race conditions live in Javascript code. (An interpreted, garbage-collected language.)

You don't understand what the memory safety promised by Rust actually does.

(No, it won't save you from buffer overruns. Only from segfaults.)


No, you can't get an RCE with an index being out of bounds in JS. You get a safe `undefined`, and a denial of service at best.

With a buffer overrun in C, you can smash the stack or other interesting structures, and put executable code of your choice in it. If you have the right kind if container breach and privilege escalation exploit lying around for the target OS, you can pwn the entire infrastructure eventually.

And no, I don't think you can memcpy / strcpy data[*i++] with abandon in Rust without first marking such code unsafe. To say nothing of concurrent modification which is another popular source of index overruns, and more.


'undefined' is never safe in Javascript.

As for the rest of your comment - good job on completely missing the point.

When we talk about "buffer overflows", privilige escalation exploits are the least of our problems.

https://hackernoon.com/null-the-billion-dollar-mistake-8t5z3...


The link you gave doesn't even mention buffer overflows. Do you have some material which explains the things you are trying to claim in more detail?


Of course undefined is safe. It is just a different kind of null, and nothing else.


You're redefining "safe" to mean "doesn't segfault".

Telling your boss that the frontend is splattered with 'undefined' and all the balances are unsynchronized, but, hey, it's not a bug because no segfaults were involved in the process is a very good way to get fired.


Can you modify a value in another part of your code through undefined?


If you are using TypeScript (which you should), undefined is not inherently any more dangerous or unpredictable than any other form of encoding missing values.


TypeScript is better than JavaScript, yes. But still it doesn't guarantee anything at runtime.


A language that always segfaults on buffer overruns is memory safe.


This reads like satire.


A previous workplace experimented with Rust for internal services and the feedback was almost uniformly negative. Commonly cited reasons were the long compile times, limited standard library, and generally unstable best practices. One interesting quote was "why are you forcing me to waste a bunch of time doing needless bookkeeping when I create and pass around a string?"

The blog post about "Why strings seem hard in Rust" was not met with excited reactions.


> "why are you forcing me to waste a bunch of time doing needless bookkeeping when I create and pass around a string?"

Rust does not force you to do this. You can in fact pass around `String`, `Vec<…>` etc, and Rust will use move semantics to make it reasonably efficient. Of course using &str and &[…] is the proper "zero overhead" solution, but it does require some extra effort.


You can also... just allow a copy to occur. My friend is always talking my ear off about how people are so afraid to copy a string in Rust, going through insane motions to avoid it, when there is some actual quadratic complexity somewhere else that's actually eating up time, whereas a single string copy is undoubtedly taking mere nanoseconds.


My guess would be that it's people (like myself) being burnt by C++'s copy semantics, where you have to deliberately and consciously avoid making copies everywhere.


I think it is the opposite in Rust. You have to specifically write `.clone()` which makes people feel like they're doing something wrong, when actually it is just a fast and harmless function call


You have to do that in Rust too. But only if you really want to avoid a copy. Who needs to avoid copying strings? Chances are that is not the slow part of your program.


Just guessing, but speaking from my own experience, the trouble came when interacting with existing APIs, where you can’t choose what to pass around.

Some expect String while others expect &str.

Once you understand why, it’s easy to intuit which one should be used where, but it was a day 1 speed bump for me.


If you have a String, passing a &str is free, you just.. put a & before your string. that's because if you expect a &str and pass a &String, the &String auto-derefs to &str. This is called a deref coercion[0]

Like, if you have fn f(s: &str), you can do:

    let x: String = String::from(something);
    f(&x);
You can see this in playground here [1] (click "Run")

To explain: both String and &str is essentially a pointer plus metadata, but &String is a double pointer (a pointer to a pointer). Rust knows how to convert double pointers to pointers, using the Deref trait. This implicit conversion is applied only in a handful of places, and only if it doesn't lead to any ambiguity (if f received a generic parameter it wouldn't work for example).

If you wanted to convert String to &str explictly, you would need to write &*x, like this (see in the playground here [2]):

    let x: String = String::from(something);
    f(&*x);
That's because if x has type String, *x has type str (because String impls Deref<Target = str> [3]) and &*x has type &str. This means that auto-deref changed your &x into &*x automatically.

[0] https://doc.rust-lang.org/book/ch15-02-deref.html#implicit-d...

[1] https://play.rust-lang.org/?version=stable&mode=debug&editio...

[2] https://play.rust-lang.org/?version=stable&mode=debug&editio...*

[3] https://doc.rust-lang.org/alloc/string/struct.String.html#im...


What language did the workplace decide to use instead?


Internal services? What problem were you trying to solve with Rust exactly?

Personally I wouldn't be writing web services with Rust, I don't think the language was really designed with that problem set in mind.


I think a lot of us with experience in "system languages" would acknowledge where Rust fits in.

But there are a lot of people in IT with experience in other fields that gets on into the marketing sales pitch that is trendy since the Java days, and i'm not blaming the community of doing anything wrong here, giving its the expected behavior of tech communities nowadays. But there is this noise into how Rust is sugared that i dont think its true, in that its the first system language that is as productive as a mid-level normally GCed language like Java or Go while giving more control and performance.

I think there is no language into that spot yet, but i think that something that follows Rust could achieve this (Its something in the middle of Rust and Swift).

The control and performance are there, as happens to C++, but the productivity is basically the same, which is not very good as compared to other languages that target more of being productive than being in control.

The control level pay out in the end in the quality of the final product, but it s not the best option for things that dont require the amount of control that C++ and Rust gives you.

But the thing with Rust, C++, Zig, etc.. is that, when you need it, you need it. There are things that can only be done with those kind of languages, and often are very complex and high-performant piece of software.

Its not for everyone, and you need a sort of commitment that you would only pay if you really need. So writing things like 'web services' on them is not optimal, and you should use languages like Go, Java et al. for this.

Tech people should be able to navigate hype and marketing lingo and see the things for what they are, i think is the same that is happening with 'web3' right now.


> The control and performance are there, as happens to C++, but the productivity is basically the same

This is not very fair to Rust. It's absolutely more productive than C++ when you account for the productivity benefits of "not shooting yourself in the foot" with pesky memory-safety bugs. Let's not even talk about scripting tools like Python, Ruby or JS that were never designed for "programming in the large" yet have somehow become popular in that role (with predictable consequences wrt. technical debt and lack of long-term maintainability).

The proper, challenging comparison is with correctness-oriented GC languages like Haskell, OCaml, possibly F#. And Rust might nonetheless have the better community, since it can address systems-level and performance concerns out of the box unlike those.


> [Rust is] absolutely more productive than C++ ...

I have spent strictly more time in the last five years filing compiler bugs than chasing memory usage errors in my C++ code. So, whatever benefits the extra work needed to make rustc happy, and time waiting on slow, slow builds is supposed to deliver, it fixes no problem I have.

The same is probably true for anybody coding C++ using modern library facilities. There is just no temptation to do anything dodgy. It would be more work than the safe thing.

So, the marketing insists on these benefits, but I don't see them. It is likely old code was more prone to such bugs, but we are talking about coding now, not then.

Rust has lots of nice features to make coding pleasant, and you can evidently get used the nannying, so it seems like an OK choice for a project that nobody else will need to maintain.


> The same is probably true for anybody coding C++ using modern library facilities. There is just no temptation to do anything dodgy.

std::string_view is but the latest example of a "modern" C++ facility that turns out to be a dodgy footgun, due to the lack of safeguards around lifetime errors. C++ still lacks a general equivalent to string_view for arrays (what Rust calls a slice) for the same reason. These seem like significant drawbacks to me.


C++ does have this, it’s called std::span.

https://en.cppreference.com/w/cpp/container/span


Just make /analyze part of the compiler options and some of those issues will be visible.


> I have spent strictly more time in the last five years filing compiler bugs than chasing memory usage errors in my C++ code.

maybe because your code isn't worth having people actively attack?


My experience is the same as theirs. In recent years I've run into more compiler bugs than memory bugs in the large, complex C++ code bases I work with.

It makes sense. A common use case for C++ today is writing high-performance software, where the software architecture is likely to be schedule-driven (e.g. thread-per-core, userspace I/O, etc). In these cases, you see minimal heap allocation, shared structures, or locking. Modern C++ is pretty safe by default for this; it allows you to do unsafe things, and to do safe things that the Rust compiler deems unsafe, but there isn't a cabal forcing people to write non-idiomatic unsafe C++ code in software architectures where the code is naturally almost entirely single-threaded and with few heap allocations.

The most insidious bugs I see in modern C++ code bases are scheduling bugs e.g. logical or behavioral edge cases due to pure async execution, which can be very subtle. Rust doesn't help with that.


As someone that doesn't work in this space, I'm interested in the schedule-driven architectures that you mention. Do you know of any talks where they explain this or, if you have some time, could you explain how the approach has changed over the past couple of decades, what architectures were common in the past, their issues, and what issues this fixes?


is your code as actively attacked as a web browser or iOS?


Good luck getting Apple to rewrite iOS in Rust, so at least that part of your argument is pointless.


no, just clarifying the difference between not encountering bugs and not having them.


Then you should have said that. This actually makes sense.

Apart from that, everyone even half competent would know that and make a trade-off involving other factors. Being dogmatic about a single facet isn't helpful.


the trade-offs are probably made to maximize profits for shareholders, and security is deprioritized as a negative externality.


>"It's absolutely more productive than C++ when you account for the productivity benefits of "not shooting yourself in the foot" with pesky memory-safety bugs"

When doing generic application level programming: use STL containers, iterators and algorithms properly and you won't have any of those pesky bugs. Does not require much efforts.

If you do want to shoot yourself C++ will of course offer thousands of ways for you to do so. But with modern C++ it has to be your choice. Unless of course you are working on some specialized system type code, libraries like STL and other similar tasks.


I don't agree it is at the prototyping level... I think C++ is quite far ahead there than Rust IMO...

For a 'stable' production implementation after prototyping, I agree that the benefits Rust provides (if it compiles, it will either panic or work) are well worth it, and so longer-term, I buy that you probably will spend less time, but in my experience, things like not being able to specify default field values inline (you need to provide a 'new' function, or 'default' impl, meaning you then have very tightly-coupled parts in different places in the code) compared to C++11's member variable inline initialisation is very fustrating when in the early stages of prototyping, when things are changing a lot.

Similarly, as mentioned above - string handling, with as_str(), to_string(), String::new(), from(), etc, I think make some sense at a full production level when you might care about ownership / copies / allocations, and want them to be explicit, but when you're just prototyping stuff to work out data structures and relationships, it's increadibly annoying IMO when you're refactoring.


> things like not being able to specify default field values inline

Rust's "struct update syntax" can be reused to do this. `MyStruct { my_field: 42, ..my_local_defaults }`, where my_local_defaults is an instance of MyStruct that's in scope.


That's not what I meant by inline.

In C++, you can set the default at the same time as you declare the member variable, meaning the three things (variable type, variable name and variable default) are in exactly the same place in the code on the same line.

In Rust, you can't do this, you need to implement new() or default() (or manually specify all field items when declaring the struct), which is normally in another place in the code, so you have tightly-coupled code in two places, which is as bad as C++ headers and implementation files which is what a lot of Rust evangelists seem to complain about on here about C++ (it's a valid complaint, but I don't think Rust completely gets it right, as is complicates / makes things more verbose in other ways like this one).


> things like not being able to specify default field values inline

I’m cautiously optimistic that Rust will get this at some point. There’s quite a lot of demand for this in the Rust community (although some opposition too)


I work at a place that has started using Rust for backend services lately and I enjoy it, but IMO using F# instead would have given many of the benefits with a lower on-ramp time for new devs and generally higher dev velocity…


Is that narrative still true post-modern cpp? On some level it feels like the cpp narrative was written in the early 2000s and hasn't kept pace with reality. Too cluttered, too object-centric, bad compile times, sure. Is the cognitive load of choosing safe pointers that much more than navigating the borrow checker?


> Is that narrative still true post-modern cpp?

The key reference on "modern" C++ is the "C++ Core Guidelines". They're pretty comprehensive but quite complex as well, and they don't really manage to establish a "sound" or "safe" idiom for the language; they're more focused on avoiding the most common pitfalls.


No, it's just an old marketing line that has failed to track reality. It is never surprising when that happens.

Once upon a time C++ was supposed to produce "code bloat". Now it doesn't, without any changes to address that.


I agree with you that one language will take the productivity you've gained in a later stage, but we would need to subtract the time fixing those bugs, as compared to the time spent on code to avoid them in both languages (one before and another later).

I'm pretty sure that a lot of people will be more productive with Rust as compared with C++ as with others will be the opposite. So i guess in by making an average over those two crowds, i doubt they will differ that much.

The sort of bugs Rust will avoid that are kind of hard to debug, giving it doesn't happen that often is the problem of shared state in a multi-thread environment.. the other kinds are often easy to spot in C++, the only difference is that they are caught in runtime.


Memory safety bugs can be intimidating and sometimes challenging. Mostly they're not though.

Conscientious programmers aren't going to spend too long in the shooting themselves in the foot phase.

To me the awful compilation model and horrendous compile times are much bigger productivity bummers.

I enjoy helping folks debug memory safety bugs that stumped them. It takes the drudgery out of the day. And it's usually an opportunity to teach them something.


Which problem sets would you say rust excels at?


As a replacement for C or C++ (except 3D games where the choice of language is dictated by the engine). Kernels, databases, CLI programs, toasters, native code Python modules, etc.

As a replacement for Go if you want a comprehensive type system instead of a skinny one.


I use C++ for backend business servers and web services in particular with stellar results performance wise. Modern C++ along with the STL and loads of 3rd party libs makes rapid development of servers piece of cake.


May I ask, what are your go to 3rd party libraries for the web service part?


For browser based applications (they're all single page web apps using json based RPC) I use cpp-httplib and rapid json. I use other as well but do not really want to get into details here. The ones I just mentioned should get you up and running in no time.


Thanks!


Not the op, Wt and asio are two known ones.

If you are into MS or AWS ecosystem there are also SDKs available for their clouds.


> Rust is a systems programming language. It offers precise control over data layout and runtime behavior of the code...

It really doesn't. It doesn't even have native support for bitfields. When I tried doing low-level programming in Rust, this immediately struck me. Rust's semantics don't really offer much of an improvement over what already existed in this area. In addition to presenting all kinds of new, frustrating challenges. I've used Ada extensively in this area, and I just don't see what Rust has to offer that Ada didn't already address. I'm all too aware that string operations in low-level programming languages are always going to be prickly. Ada's standard library, even in its 80s incarnations, is light-years ahead of Rust in this area. Interoperability with other languages is another area where Ada beats Rust hands-down. The first thing I tried to do was integrate C and Rust, and realised immediately that it was a nightmare. In Ada, it really couldn't be simpler.


> It really doesn't. It doesn't even have native support for bitfields.

Many people would consider C bitfields half-baked in the first place, given that the feature is well-known to be underspecified in a way that leads to compatibility/portability concerns. Is this really the kind of stuff that Rust should concern itself with?


Yeah I agree with rust's decision to not go there yet. They're only really used often in very low-level niches like mmio registers, where autogenerating handlers with svd2rust works great and provides a little bit of safety along with it.

This is coming from someone who uses C bitfields every day on an embedded MCU.


> They're only really used often in very low-level niches like mmio registers

... which are actually an incredibly common, totally everyday problem encountered by tens of thousands of developers everyday?

> autogenerating handlers with svd2rust works great and provides a little bit of safety along with it.

I don't think that requiring third-party tooling to implement something so basic is a suitable solution to this problem. What if the manufacturer of the device I'm working with hasn't released an SVD file? What if I'm not actually working on an MCU at all, but a peripheral driver?


> actually an incredibly common, totally everyday problem encountered by tens of thousands of developers everyday

I never said they're umcommon. As I said, I user them all the time. They're incredibly common in specific fields. There are many systems programmers who barely ever use them.

There are a lot of footguns with bitfields in C. (1) they know nothing about defaults, (2) they have no way of restricting values beyond bitwidth, (3) they are often inefficient, producing multiple load-modify-stores for what is really a single operation, (4) they are not endian portable.

svd2rust addresses all of those: (1) it knows what the defaults are and you can tell it to load them for you, (2) it will restrict the values for each field to only those that are valid (you can use unsafe to bypass the check), (3) it produces a single load-modify-store (or less) for any given operation, (4) it produces shifts and masks internally so doesn't depend on the compiler to behave as expected.

Of course, C bitfields don't require tooling, and I'd say they're a little easier to use. It's a trade-off, and I personally prefer the rust side.

> I don't think that requiring third-party tooling to implement something so basic is a suitable solution to this problem.

Don't most people auto-generate bitfields, too? Like sure, writing a couple by hand is fine, but I didn't think that's typical.

> What if the manufacturer of the device I'm working with hasn't released an SVD file? What if I'm not actually working on an MCU at all, but a peripheral driver?

You can write your own SVD, or write yaml and convert that to SVD. I think that would probably work for a peripheral driver, too.


Bitfield equivalent constructs are used more ubiquitously than just embedded. For example, in database engines the size of internal types are often defined in bits that aren't multiples of bytes, and they are packed and composed accordingly. Good implementations use a bit of meta-programming magic to make them seem more natural but they aren't something C++ was really designed to support.

I think there is an opportunity for a systems language to do bitfield types right, which means not copying C.


I agree that there's certainly usefulness for bitfields in the industry, but I haven't seen a good proposal that addresses the main issues that C bitfields have. And in rust, any given proposal wouldn't be super useful if it always required unsafe.


The Rust standard library should concern itself with very general patterns that could feasibly enable interoperability across crates. I'd rather see a generalized facility for working seamlessly with composable 'optics' on Rust structs/objects (similar to the existing support for Iterators) than something strictly focused on the bitfield case.


Bitfields are a construct that I use all the time in my work. If Rust chooses not to implement semantics for defining bit-level fields, then it's just harder for me to accomplish what I need to using Rust. Again, bitfields are something that Ada makes simple, and easy. Granted, I think Ada's syntax for this could be improved.

I don't see the relevance in pointing out that the C standard has problems related to bitfields. Rust is supposed to be an improvement upon C.


> If Rust chooses not to implement semantics for defining bit-level fields

Look, it's not that hard. Just write getters and setters for the underlying structs, and you'll pretty much reach parity with what C gives you (but in a well-specified way). There are crates that will make this easier.


“Language X has implemented this badly, why should language Y bother with it” isn't really a convincing argument.


> I've used Ada extensively in this area, and I just don't see what Rust has to offer that Ada didn't already address.

Memory safety guarantees that don't go out the window if you ever need to free a dynamic allocation, for starters.

Bitfields are an underspecified minefield in C, I don't think it's as clear of a loss as you're making it sound.


> Memory safety guarantees that don't go out the window if you ever need to free a dynamic allocation, for starters.

Lots of people like to repeat this without understanding all of the other controls that Ada has for access types (pointers).

Ada access types (like pointers) are typed so you could make multiple equivalents of `Foo` that can't be mixed and matched. e.g. one version of `Foo` might be for one subsystem and another version of `Foo* for a different subsystem, which would prevent you from giving an allocated object from one system to another. You also can't point an access to any arbitrary location without it being specifically marked with `all`, and there's limitations to how you can use an access that gets passed as a parameter. Due to these factors, how allocations can be used gets constrained and with Ada's support for RAII ("controlled types"), these details usually get hidden internally within types. It's not a specific block section like `unsafe`, but your unsafe memory usage is helped by the type system.


Like I said above, I don't see the relevance in pointing out that the C standard has problems related to bitfields. Rust is supposed to be an improvement upon C. Ada managed to implement a standard for defining structures at the bit level in a portable way back in the 80s. Saying that Rust can't do it now because the C standard doesn't sufficiently specify bitfield semantics isn't a good answer.


> Saying that Rust can't do it now because the C standard doesn't sufficiently specify bitfield semantics isn't a good answer.

I don't think anybody is saying that? Particularly given that Rust is working on precisely that.

The argument is merely that not currently having a good bitfield solution is hardly a showstopper for systems development, given that C is already far more popular in that area than Ada despite its deeply deficient version of bitfields which leads to them being banned in a great many codebases.


To be fair, the problem with C bitfields that causes them to be forbidden in many coding standards is that don't offer "precise control over data layout". They are underspecified, so a lot of C/C++ code bases construct bitfields explicitly and manually (and these have other advantages anyway). And of course you can do the same in Rust.

Rust has limitations as a systems language but this isn't one of them.


What do you mean this isn't one of Rust's limitations? It's a common, well-understood feature of systems languages, which Rust doesn't have. Look for yourself on Rosetta Code[0]. There are many languages that feature a way to define a structure with individual bit fields: Basic, Fortran, Ada, etc.

[0]https://rosettacode.org/wiki/Memory_layout_of_a_data_structu...


Bitfields are hard! They are potentially unaligned, thus interact poorly with some language features, like pointers and references. And their size isn't a multiple of bytes, unlike any other value, which causes problems as well. They interact poorly with padding and the general idea of Rust ABIs that enables optimizations like reordering fields and using "niches" (invalid values) to find a more compact layout for structs and enums.

I agree Rust should eventually have some native support for bitfields, but only if it's a high quality spec that addresses the outstanding concerns - Rust should specifically avoid the C mess, which isn't usable for most projects.

But this doesn't mean bitfields can't be done in Rust; it's just not in the stdlib (yet). See this post[0] which contains a survey of various libraries (and their respective limitations), and this slightly older article [1]. Those articles somehow missed the modular-bitfield crate [2], which is perhaps the nicest to use, and is what I would recommend you.

If you don't care about the specifics you can get any crate discussed in the above articles and use them.

About interoperability with C (and C++), I really like bindgen, cbindgen and cxx. The bindgen book [3] is straighforward. This section of cxx documentation [4] also describes the tradeoffs between the different FFI approaches. I don't know Ada though, so I must ask: what does Ada do?

About this,

> I just don't see what Rust has to offer that Ada didn't already address.

Off the top of my head, the crates ecosystem, the borrow checker, sum types with pattern matching [5], a stellar story for error handling (beats any language I know hands down - that is, if you use crates like thiserror and anyhow).

[0] https://immunant.com/blog/2020/01/bitfields/

[1] https://myrrlyn.net/blog/misc/bitfields-in-rust

[2] https://crates.io/crates/modular-bitfield

[3] https://rust-lang.github.io/rust-bindgen/

[4] https://cxx.rs/context.html

[5] https://chadaustin.me/2015/07/sum-types/


> Bitfields are hard! They are...

Again, like so many others in this thread, you're talking about C's problems. C is not the only language to implement this feature. I keep bringing up Ada because it's a language that features the ability to define structures at the bit level in its core language semantics. It manages to do this in a portable way, with a much more sophisticated, not to mention sound type system.

> But this doesn't mean bitfields can't be done in Rust...

Why should users need to rely on installing third-party additions in order to do something so basic like this? With the addition of third-party frameworks, and tooling you can make C as safe as Rust too, so I don't think the argument that third-party dependencies can solve this problem are relevant. I'm judging these languages simply on how well they allow me to express the semantics required for low-level programming.

> About interoperability with C (and C++), I really like bindgen, cbindgen and cxx. The bindgen book [3] is straighforward...

Ada comes out of the box with this functionality. It doesn't require reading a 'book' to understand it either, it's very straightforward.

> beats any language I know hands down - that is, if you use crates like thiserror and anyhow...

Again, why should someone need to install third-party tooling and dependencies for such basic features? The fact that so many responses list a litany of external dependencies to address Rust's shortcomings does not lend much credibility to Rust's design.


The main reason I don't complain about rust is because complaints feel like a way to pressure developers to address my specific wish list, which feels wrong. But, this thread feels like an opportunity, so here goes:

1. It lacks a good way to control memory in different ways for different data structures. The allocator_api is still experimental. This feels strange for a systems language.

2. It's a complex language. There's no way around that. The developers have done a great job avoiding unnecessary complexity, but the benefits rust offers do have a complexity cost and you should really evaluate whether rust enables you to make up for it with simplicity elsewhere in the stack.

3. The sync/async situation feels like a division to me. Maybe that's inherent and not rust's fault, but it does feel like some kind of a divide. For instance, if you want a postgres driver, rust-postgres is great, but it follows the async approach and that means zillions of dependencies and long fresh-compile times. If it used a synchronous style, it would only depend on the standard library, and compilation would be very fast. Should there be two libraries? I don't really know.

4. There's not a good supported way to build "plugin" style shared libraries where you can refer to symbols that exist in the program that loads the library. You can hack the build flags in, but none of the testing infrastructure works.

5. While C integration is great, there's not a good way to catch a longjmp() from C without some undefined behavior.

6. The culture of rust seems to favor dependencies a bit too much. The decision to take a dependency is an important one with trade-offs, and the rust culture seems to be always to take a dependency, even if doing it yourself would be little code, and the dependency transitively includes a ton of code that seems to churn a lot. This plays to rusts strengths around tooling, but goes to far in my opinion.

But after all of that, there's still one huge reason to pay attention to rust: if you are a systems programmer, there aren't a lot of options for most projects, so having a new option is a big deal. In many cases, the practical options go from "C/C++" to "C/C++/Rust".


This is a much better level! I think you really should write an article about that. Criticism like this is no pressure, I think - it's an essential part of discussions and the evolution of language.


Since life is short and time is not unlimited and I'm not a talent programmer, I have decided to stick with c/c++ plus some python/golang/javascript/sql for my software career all the way until it ends. Those are already more than enough for me to handle in fact.

best luck to rust programmers, it's just too much for me and too late for me. I do use quite a few nice rust utilities(fd,rg,etc) daily.


if c/c++ really includes having good C++ knowledge then Rust will be kindergarten, promise


This is why I don’t understand why people insist on creating web frameworks in rust. It’s one thing to write a proxy server or load balancer in rust, it’s another thing to write your actual CRUD app in rust. And the community has bent over backwards to support this use case and expended enormous resources to that end.

I write embedded firmware, replacements for GNU coreutils, system services, and more in rust and I love it. But I write my web apps in C# and I wouldn’t change that.


Fair enough, and I think I mostly agree. But it's worth pointing out that large amounts of the web facing services from FAANG companies that we all use daily ... are written in C++. They could just as easily be done in Rust.


For these things, languages with gc should really be used.


If people want to write things in Rust, let them write things in Rust.

Hanging out at community Discord I see that there are a lot of new guys, students. They just want to experiment, and I am all for it.

Yes, maybe it's not the most efficient thing from "business perspective", but maybe, eventually something new and exciting will come out of it.

Programming is evolving, we had a lot of the same functionality available in older languages, using older paradigms, but eventually those stay in the past for a reason.

I'm staying open minded and I am excited for the future.


I agree. Rust is not the right language for this, unless performance is the #1 concern (but mostly it is not).

I'm looking forward to have something like Linux written in Rust though.


>However, in many (most) cases, one doesn’t need ultimate performance or control over hardware resources. For these situations, modern managed languages like Kotlin or Go offer decent speed,

I feel like D really deserves to be mentioned more often when talking about Rust alternatives. It's sort of the anti-Rust: improving on C++ by focusing on ergonomics rather than raw efficiency. It's likely more familiar to the C++ native than Kotlin and Go, and more directly comparable to Rust in that it has an expressive type system, compiles to native code, and interfacing well with C.

I would say D is the best answer on average to the question "I like all those things Rust can do but I find it annoying to work with, what can I use instead?" whereas Kotlin or Go will not always be a great stand-in.


The community is great, but D itself kind of suffers from lack of direction where they want to be, every couple of years there is this next big that is going to bring people into the community, none of them fully done to completion ironing all bugs out.

So it remains a very nice language, but you need to be willing to get hands dirty fixing bugs and contributing back, if you feel going into production with it.

All D success stories had their of fork of the D toolchain, or standard library, to certain extent.


If you consider Symmetry investments a D success story, we do not do that - we do have a fork of LDC but I've never needed to use it, as far as I'm aware it's just an early release in effect, no new features.


Good to know, although the point was not about new features, more like bug fixes and the alternative runtime as Sociomantic used to have.

More than a sucess story, I consider Symmetry the very last hope to keep D relevant actually.


A programming language that offers no mechanism to handle memory allocation errors is not a system programming language. I have yet to come to a conclusion on the merits of Rust, but this claim about system programming always ticks me off.


First, I feel that is a bit of gate keeping. I've done a lot of systems work where Rust today would have been perfectly fine. We originally tried to track memory allocation errors but we gave up because we didn't test allocation failures and likely had large gaps in it and just found it wasn't worth the code bloat. We still checked for allocation failures for data transfer buffers but thats it.

Second, Rust doesn't stop you from handling memory allocation errors. The standard library might fully support failable allocations but that doesn't stop you from using your own collections for that type of work.

Third, this has been an item of interest for a long time in the Rust community and is actively being worked on as part of introducing Rust into Linux.


It does not take much sophistication to end up with multiple allocation arenas, any one of which might be exhausted without indicating general system failure.

Being ill-equipped to use or recover from allocation failures in such arenas bodes poorly for a systems language.


If you’re allocating from multiple arenas, you’re not going to be using `new` in C++ or `Box` in Rust. Nothing stops you from writing an arena allocator that can return an error code in Rust any more than C++ does.


If you run nightly you can already Box::new_in(thing, my_allocator) if that is what you want. Or indeed, if you want to keep Nathan here happy, you can even Box::try_new_in(thing, my_allocator) and get Errors when your allocator says it can't help you (which you likely won't ever bother handling meaningfully).

In the event you're as desperate for those last dregs of performance as the author of the "Why not rust?" article, (and let's assume you actually measured your performance problem before jumping to the step where you make everything more complicated and more buggy for no good reason?) you can even Box::try_new_uninit_in() and unsafely do all the initialization in place as needed yourself as you might do by default in C++.

Now, I don't know when Allocators will be stabilized, the Working Group has been making steady progress for some years now but this is a tricky business, witness the many languages that get it quite badly wrong...


Imagining that any of this has to do with "last dregs of performance" demonstrates that you have completely misunderstood the topic.


Hint: nobody uses "new" in C++ anymore. All the C++ containers, and make_unique etc. know how to use local arenas.

I gather there has been some effort to get Rust library components aware of such things. Handling exhaustion in them is an interesting research topic.


> Hint: nobody uses "new" in C++ anymore

"nobody"

    ~/chromium (main)$ rg --stats -t cpp "[=\(][ ]*new "    
    ...
   
    17639 matches
    17536 matched lines
    7162 files contained matches
    96561 files searched
    1539692 bytes printed
    763109193 bytes searched
    1.119265 seconds spent searching
    1.428974 seconds
That's surely a lot of non-usage. Maybe it's just Chrome, though?

    ~/llvm-project (main)$ rg --stats -t cpp "[=\(][ ]*new "
    ...
    7447 matches
    7394 matched lines
    2245 files contained matches
    35148 files searched
    541938 bytes printed
    385115019 bytes searched
    0.425689 seconds spent searching
    0.485431 seconds
Hmmmm.


You have found lots of old code.

... which we already knew existed.


> We originally tried to track memory allocation errors but we gave up

I hope it wasn't a safety-critical application.

> Rust [...] doesn't stop you from using your own collections for that type or work

and your own replacements for all of their dependances. Remind me why I need Rust again.

> this [...] is actively being worked on

I'm looking forward to learning Rust when it becomes worthwhile. For now it seems that asking about allocation errors in Rust on HN is like asking about nuclear waste disposal for next generation reactors. Answer: never mind about that; look at all the cool safety features.


That's not a limitation of the language, that's a limitation of the current standard library. This is being revised to match expectations of the Linux kernel development, which by no means encompasses every aspect of "systems" programming.


> Ada is memory safe if you don’t use dynamic memory (never call free).

Take a look at https://docs.adacore.com/live/wave/spark2014/html/spark2014_....

You can prove the absence of memory leaks, too. :)


Leaks are permitted in rust, and are not a memory safety concern. I don't think that's what he was talking about.


I just added that as an extra. The point is that you can have memory safety even if you do free. It may not have been the case with Ada (without SPARK) in the past.


I would also like to add these:

> Values of such an access type can be deallocated safely. GNATprove generates verification conditions to ensure that no memory can be leaked.

So... you can deallocate safely AND verify that no memory is leaked. Is it not wonderful?

- https://docs.adacore.com/live/wave/spark2014/html/spark2014_...

- https://docs.adacore.com/live/wave/spark2014/html/spark2014_...

> SPARK builds on the strengths of Ada to provide even more guarantees statically rather than dynamically. As summarized in the following table, Ada provides strict syntax and strong typing at compile time plus dynamic checking of run-time errors and program contracts. SPARK allows such checking to be performed statically. In addition, it enforces the use of a safer language subset and detects data flow errors statically.


I've been prototyping a little program to manipulate disk image files. I chose Rust, because I wanted to see for myself what the big deal was. It's not a good language for prototyping. I think Rust will always be known as "that language you rewrite your code in once you know exactly what you want, and need to make it secure"


> Rust is a systems programming language. It offers precise control over data layout and runtime behavior of the code, granting you maximal performance and flexibility.

I'm nitpicking, but it's due to considering the difference important for some unsuspecting programmers: having control over data layout and runtime behaviour doesn't grant you maximal performance. It grants you capability for achieving minimal overhead, which is connected to, but a different thing from performance.


Thanks, it’s a really great way to put it!


In my limited experience the compile speed issues are often overblown. The biggest rust project i compile regularly is deno. It doesn’t feel that slow.

Cargo is great but it’s not continued to evolve fast enough. For example, there’s not enough defence against supply chain attacks yet.

>> Rust’s price for improved control is the curse of choice

The annoying unstated side effect of this is that on average, developers will choose the easiest option. E.g. quite a few blogs and tutorials wastefully use clone because it’s easier than wrangling with lifetimes (which admittedly have an developer-unfriendly habit of being quite virulent through your code) - or whatever other approach you fancy to avoid pointless copying. They do it just to get around the borrow checker. You don’t need to be processing that many strings with this approach before Python’s (lack of) speed is giving you a run for your money.


I really want to love Rust. The resulting programs written in it are fast, memory efficient and safe. Something which usually isn't the case in other programming languages. But here and there I see how simple problems require complicated solutions, for example when you want to create a logger middleware for a web service: https://youtu.be/16sU1q8OeeI

Something I could have written in 3 lines of JavaScript. In Rust, it requires knowledge of poll, pin, boxpin, ... and even third-party crates (if you yourself are not enough of a magician). I'm not sure if Rustaceans are okay with that additional complexity, but it really scares me off to dig deeper into that language. I would appreciate if some experienced Rust programmers could comment!


| keep in mind that picking Java over Cobol for banking software in 90s retrospectively turned out to be the right choice

Is the Java written in the 90's still the same Java written today? I feel the mentioned Lindy effect equally applies to dialect. C++ today is radically different to C++ from the 90's. I'd venture COBOL from the 90's is likely quite similar to COBOL today.


Looking at the Wikipedia page for Cobol 2002 and 2014, the last two major releases, it looks like they've gained features such as Object Oriented Programming, Recursion, data types like Booleans, pointers, and user-defined functions. So I'm going to bet modern COBOL looks totally different to that of the 90's!


I spent ~5 years working on a COBOL compiler. In practice, production COBOL compilers pick and choose which parts of the standard they choose to implement based on customer demand, and there's not a lot of demand for most of the new stuff. To a first approximation, almost all COBOL code is legacy code in maintenance mode, and I would guess that a significant fraction of COBOL running today has barely been touched since the 90s, if not earlier.


I'm still waiting for concurrent COBOL...

PERFORM x CONCURRENTLY WITH y BUT NOT WITH z.


  000100     MOVE 4 TO reference-count ATOMIC IF reference-count EQUAL TO 3.


I'm also curious about the architectural consequences of Rust. It seems to force us into a very procedural or functional style, and sometimes makes us use parallel collections for things in a way reminiscent of relational databases... which is often a good thing, but not always. I'd love to read others' opinions on the topic.


One of the things I valued in the C++ community is the idea of expressing underlying complexity more explicitly through language / API constructs to help steer people in the right direction (Pit of Success type of stuff). I feel like Rust is taking that further and helping show how nasty most of our GUI (at least) architectures are.

I eagerly watch the progress of GUIs and other architectural work in Rust because they are helping to raise the popularity of solutions we've been ignoring because things have been "good enough".


React and Polymer seemed like an okay balance of of OO and functional... are our current GUI architectures really that nasty?


I'm speaking of more traditional GUI architecture where everything is a bidirectional graph of statically defined widgets. From my understanding, Elm and react style GUIs are some of the models people are looking to in Rust.


GUI in Rust specifically is very unpleasant, from my limited experience.


Rust is just a (pretty opinionated) tool. When it works, it really works, and the architecture rises smoothly. When it doesn't work, it really doesn't work, and there's some teeth gnashing and maybe a little praying Zig reaches 1.0 soon.

People want a be-all-end-all tool, but Rust is just not that, so you get tons of arguments about this or that use case. You wouldn't use a saw to hammer in a nail. Just treat it like a tool.


I'm someone who likes to write Rust and wants to use it all the time, but for my professional work I only choose it when I really need it, which is very seldom - actually it was only once for a CAD data converter where memory usage must be as low as possible. The reasons not to use it always for everything are:

1. The mental overhead is larger than most want to admit. It's not about the syntax, but about memory management of course. The time and effort spend there should be spend to solve the problem at hand.

2. Depending on a lot of third party libraries which are maintained by just 1 person.


I'm glad to see this article, every week I roll eyes at people on HN claiming that rust targeting wasm will replace javascript. I'm not against replacing js, it just won't be a language that's made on the complete opposite side on the spectrum of PLs.


Or appearing in every other language discussion to bring up Rust.


Interesting note - when it comes to compile times, the most optimized Rust codebase in that aspect I believe is makepad.dev [1].

It is compiling from scratch on mac m1 in around 7.5s [2] and that's +100k lines of Rust. However there is close to none dependencies, so this +100k is all there is to compile pretty much. Still, this is impressive feat!

[1] https://makepad.dev/

[2] https://twitter.com/rikarends/status/1467529091284934666


The linked presentation deck "High Performance Managed Languages" is great!

Deck PDF: https://qconlondon.com/london-2017/system/files/presentation...

Video: https://www.youtube.com/watch?v=Pz-4co8IaI8


> modern managed languages like Kotlin or Go offer decent speed, enviable time to performance, and are memory safe by virtue of using a garbage collector for dynamic memory management

Take this with a grain of salt: Go data races can still lead to memory corruption and security vulnerabilities (no one uses the inbuilt data race detector in production, few use it while testing).


Discussed at the time:

Why Not Rust? - https://news.ycombinator.com/item?id=24536645 - Sept 2020 (319 comments)


> But, for example, some runtime-related tools (most notably, heap profiling) are just absent — it’s hard to reflect on the runtime of the program if there’s no runtime!

Yeah; I felt that pain too.

I tried to write something to address some parts of the missing space. It's still in the early stages but you may be interested:

https://github.com/mkmik/heappy


The most important argument is that not all programming is systems programming.

A lot of projects choose C, C++ or Rust only because they need performance:

* Backend services

* Numerical computation

* Game development

* Rendering engines, e.g., browser engines

System programming is usually needed for what we consider Operating Systems, e.g. kernel, system libraries, and shell.

In my career as a C++ programmer I have worked on a lot of projects that I would otherwise write in C#, Java, Julia, or Go.


I'm in the camp that is long-term bullish on Rust. Memory safety is simply too important. I also consider C++ an unsalvageable mess at this point. Just a couple of thoughts reading this.

> Compile Times

This is (IMHO) the biggest problem with Rust as the article mentions. Apparently, this was due to some early unfortunate design decisions that resulted from the tight coupling with early Rust and Servo. Rust at this point is heavily tied to LLVM (I'm aware there's a gcc version in the works).

If you don't know, the general structure is LLVM is to have a frontend and a backend. The frontend translates whatever your language is into LLVM-IR (intermediate representation), a sort of abstract assembly language. This isn't tied to any particular architecture (eg IIRC there are infinite registers in LLVM-IR). The backend translates that to a particular architecture. This is good because it's easier to get a compiler off the ground but gcc's performance is still second-to-none.

Rust expands macros and the likes by producing a godawful amount of LLVM-IR and lets the backend strip out what's not needed. This works but impacts compile times.

More details here [1].

> Complexity

Yes and no. It's a bit like how dynamic programming languages originally rose to prominence because of the speed you could do things, or at least that was the argument. Static typing was seen as getting in the way or being too complex. I've come to the conclusion that this is a false economy. The best way I can put it is in Python you end up writing unit tests for spelling mistakes.

The hierarchy of programming errors is IDE errors are better than compiler errors which are better than runtime errors. In an ideal world there's no difference between IDE errors and compiler errors but almost always there is.

So Rust is actually forcing you to move runtime multithreaded issues into being compiler errors. This feels like more work (because it is) but it is infinitely preferable. Opponents will say, for example, that C++ has smart pointers to denote ownership. This is true but they have a runtime cost. Rust doesn't. And the effect of a runtime error in C++ is typically a core dump or just weirdly inconsistent behaviour (which is often worse).

People routinely underestimate just how complex multithreaded code really is, particularly when they try and write lock-free abstractions (as is popular in C++) especially given the complexity of how processors actually work (eg out-of-order execution, branch prediction). There are various tools that are written to identify some of these issues (eg valgrind, asan, tsan, etc). While I was at Google I remember reading about how a bug had been found in an in-house written lock-free abstraction with some new tool that had been >7 years in production.

But yet, even on HN, I too often hear "what's so hard about just putting a mutex on it".

[1]: https://pingcap.com/blog/rust-compilation-model-calamity


> If you don't know, the general structure is LLVM is to have a frontend and a backend. The frontend translates whatever your language is into LLVM-IR (intermediate representation), a sort of abstract assembly language. This isn't tied to any particular architecture (eg IIRC there are infinite registers in LLVM-IR). The backend translates that to a particular architecture. This is good because it's easier to get a compiler off the ground but gcc's performance is still second-to-none.

Virtually every modern compiler is implemented using this approach - including GCC. GCC also used to be quite a lot slower than clang, but just like with error messsages, the GCC people have put a lot of work into it.


>So Rust is actually forcing you to move runtime multithreaded issues into being compiler errors. This feels like more work (because it is) but it is infinitely preferable. Opponents will say, for example, that C++ has smart pointers to denote ownership. This is true but they have a runtime cost. Rust doesn't. And the effect of a runtime error in C++ is typically a core dump or just weirdly inconsistent behaviour (which is often worse).

Rust has full set of smart pointers: Box (unique_ptr), Rc, Arc (shared_ptr), and in addition to it RefCell to work around limitations of borrow checker. All of these are very widely used in almost any real world project.


One of the main benefits of Rust, memory safety, becomes much less significant when compiling to the wasm sandbox. Thus in this setting I prefer to use modern C++ over the (at times horrible) verbosity of Rust.


Catching those at compile time is still much better than some obscure runtime bug. If the latter would be enough, valgrind would suffice for testing c/c++ programs, but you can’t really execute every code path all the times.


I wrote all my code in Pascal to have fast compilation

With reference counted strings/arrays, it has solved almost all memory safety issues for me.


Memory safety is easy if you use GC (so don't have to define lifetimes) and mandatory bounds checking (unless compiler/JIT can convince itself that it is not necessary). Arguably these tradeoffs are the correct choice for a large majority of all applications — developers agree, looking at the popularity of Python, Java, .NET, Go, PHP, Perl, ...


The biggest leak I’ve seen was in the JavaScript (qml) side of a C++/qml app. You can still leak in GC languages by inadvertently holding on to things you are done with. The GC encourages you to not think about it, which is a problem.


I disagree. Just because there is a GC, it doesn't mean one does not have to be aware of the existence of memory. OOM errors are thing even without leaks in GC languages.

Besides, leaks are only a small part of memory safety anyways.

And I'm not surprised that you find the biggest leak in Javascript, the language that probably the biggest percentage of amateur/inexperienced developers are working in. (which is not generally a bad thing, but increases the chance for these bugs)


Agreed. At a certain point thinking about garbage collection becomes more burdensome than just handling allocation explicitly.


There reference counting has an advantage of being deterministic, so it is easier to reason about than full garbage collection


I don't consider memory leaks a memory safety issue since all they do use use up memory and cause failing allocations, which has to be handled one way or another regardless whenever you use dynamic memory.


This was written in 2020


Nothing mentioned in it is any different now.

That Pimpl is not practical in Rust is interesting news to me.

The author's blithe unconcern about Cargo dependency trees looks unwise just now.


My heuristic nowadays is if the workload is I/O bound, use Go. Otherwise, use Rust.


The trouble with "why not" questions is it implicitly omits the reasons why.


(2020)


The first “point” made me read the whole article skeptical. 1) Rust is a “general-purpose programming language”, not “system programming language”. 2) Performance is not even the most important reason. Syntax, features, guarantees - much more important.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: