Hacker News new | past | comments | ask | show | jobs | submit login
I Hope Rust Does Not Oxidize Everything (gavinhoward.com)
99 points by gavinhoward 3 months ago | hide | past | favorite | 180 comments



The author seems very anxious because Rust is getting traction and they don't like Rust. They're afraid that one day Rust will become a "monoculture" and everything will be written in it.

I like Rust, but I consider this very, very unlikely.

Rust has actually brought more choice to the programming language scenario. If we're talking about monoculture, let's talk about C/C++. For decades this was the only viable option for systems programming. All new languages were focusing on a higher lever. Languages for lower level stuff were rare. There was D, but it never got enough traction.

Then Rust appeared and there is finally an alternative. And not only that, I because of that, other language designers decided to create new systems languages, and now we have Zig, and Odin, and Vale, etc.

So if anything, Rust is helping in breaking the monoculture, not creating it. C and C++ are not going away, but now we have alternatives.

And I think it's important to acknowledge that even if you don't like a language, if you see a bunch of software being written in such language, it's because the language is useful. I don't like C++ but I admit it's damn useful! People are writing interesting software in Rust because they find it useful.


Rust is challenging people because it declares several long-inadequate things about C/C++ to be inadequate (security issues, dependency management), and provides alternatives which show that it doesn't have to be like that.

The rewrites will inevitably be long and painful. Rewrites always are. But the onus on anti-Rust people is now to demonstrate a better language to rewrite in first, rather than just sitting in the status quo waiting for the steamroller driven by a crab to very slowly run them over.

D is interesting but seems to be a solo project, I'm not sure why it's not had traction. Maybe it's not different _enough_.


This is not meant as a critique of you, but your comment includes a hint of what bothers me with some Rust evangelists. I would call it "slightly entitled over-optimism".

I have a C++ service running in production. It's been in production for 10-ish years with minimal updates. It'll probably keep running just fine for the next 10 years.

With that in mind, "the onus on anti-Rust people is now to demonstrate a better language to rewrite in first, rather than just sitting in the status quo waiting for the steamroller driven by a crab to very slowly run them over." just doesn't make much sense to me. If the status quo is fine, there's no "onus", there's no difficult decision to be made, there just isn't any rewrite. The anti-Rust people will probably be fine by doing ... nothing.


> I have a C++ service running in production

Is it on a network (or other) security boundary, exposed to attack from the Internet?

Is it deployed on millions of machines worldwide?

_Those_ are the primary targets for replacement, because the networked environment is a very hostile place, and people are fed up with the consequences of that. Regular announcements of "sorry all your private data has been leaked lol". Constant upgrade treadmill to fix the latest CVEs.

(the poster child for this was really Shockwave Flash, later owned by Adobe, which had so many RCE exploits everyone united behind Apple killing it off. Even if this meant obsoleting a whole era of media and games which relied on it. That wasn't rewritten, it was just killed.)


I'd guess most services where performance matters are in the background. And this particular C++ service is only accessible over internal LAN, to be used by other back-end servers.

I agree with you that if ha-proxy and nginx didn't exist yet, they would be prime candidates for being implemented in Rust. But now that they already exist and reliably work, I'm not sure there is enough pain for them to get replaced anytime soon. BTW the last ha-proxy CVE was them differing from the HTTP spec and accepting the # character in additional URL components, which is something that probably no compiler could have flagged.


> I'm not sure there is enough pain for them to get replaced anytime soon.

https://blog.cloudflare.com/how-we-built-pingora-the-proxy-t...

https://blog.cloudflare.com/pingora-open-source


That sounds like a great project :) but

1. "Pingora is Not an Nginx Replacement" https://navendu.me/posts/pingora/

2. you still put it behind ha-proxy https://github.com/cloudflare/pingora/issues/132

3. https://github.com/cloudflare/pingora says "Pingora keeps a rolling MSRV (minimum supported Rust version) policy of 6 months." so for anyone who dislikes the "constant upgrade treadmill", this won't help much.

So my summary would be that Pingora is a great Rust library which one day might be used for replacing nginx and/or ha-proxy.

But the main advantages of Pingora - which are the reason why CloudFlare is using it now - have nothing to do with Rust. Obviously, a software architecture designed in 2022 can take advantage of modern hardware in a way that an architecture from 2004 cannot. (Yes, nginx is that old). Intel's TBB library brought "work-stealing" to C++ around 10 years ago. The other big improvement in Pingora is moving from multi-process to multi-threading pools. Again, C++ had thread pools for years.

So Pingora is probably great and it's written in Rust. But the business benefits that it brings aren't coming from Rust. They are coming from the fact that it's a modern architecture.


> But the business benefits that it brings aren't coming from Rust. They are coming from the fact that it's a modern architecture.

This is moving the goalposts. Your original post said

> I'm not sure there is enough pain for them to get replaced anytime soon.

Yet, here one of them is, being replaced at a company that powers ~10% of the traffic on the Internet.

But beyond that, your links:

> 1. "Pingora is Not an Nginx Replacement" https://navendu.me/posts/pingora/

Here's what the start of the post actually says:

> Think of Pingora as an engine that can power a car while you have to build the car yourself. Nginx is a complete car you can drive. River is a faster, safer, and an easily customizable car.

The title is being pedantic for effect. It doesn't say what you say it's saying.

> 2. you still put it behind ha-proxy https://github.com/cloudflare/pingora/issues/132

This is an issue opened by someone on an open source repository. They aren't talking about how Cloudflare itself uses it, but about how they want to use it.

> so for anyone who dislikes the "constant upgrade treadmill", this won't help much.

Similar to above, this is moving the goalposts. Sure, that might be true, but it's unrelated to the original topic.

> But the main advantages of Pingora - which are the reason why CloudFlare is using it now - have nothing to do with Rust.

This is not what Cloudflare themselves would say. They chose Rust for very specific reasons when building Pingora: (repeating the link from above) https://blog.cloudflare.com/how-we-built-pingora-the-proxy-t...

> We chose Rust as the language of the project because it can do what C can do in a memory safe way without compromising performance.

Cloudflare has been a vocal proponent of Rust for years now. Many years ago, they suffered a very serious bug, CloudBleed, that Rust would have prevented. And so they've been using Rust instead of C and C++ for a long time.

They of course would also very much agree that the architecture matters, but that doesn't mean that the implementation language doesn't matter either. If they chose to implement Pingora in, say, Ruby, that wouldn't have accomplished their goals.


I don't think anyone believes there will be no C++ codebases in the future - that's crazy talk. What could happen in a decade or two is that there'll be no _new_ C++ codebases. Popular languages are retired to legacy status from time to time, and C++ is completely outclassed by Rust.


People love to think that C++ is only used in systems programming, the thing is C++ is used everywhere.

FORTRAN is being developed and improved, and new code, most notably in scientific domain, is still being written.

What Rust did to C++ is what clang did to GCC. Wake the giant up. Rust will go nowhere, but it's the same for C++.

Thinking that C++ will just fade to black is wishful thinking.


Since C++ still evolves and changes, I guess greenfield C++ projects in the future can limit themselves to a subset of the newer improved language thereby C++ will continue living by that way as well.


The C++ community is talking about evolving in the following ways in this space:

  1. contracts
  2. profiles
  3. successor languages
  4. borrow checking
The idea of a "subset of the language" is one that's often talked about, but there seems to be an explicit rejection of the idea of a subset, at least by several important committee members. It's not clear to me why this is the case.


I’m not sure why you’re getting downvoted. The committee members have clear interest to keep things as they are. However, from a practical perspective I suspect that “subset lang” will happen. One just needs a linter or compiler flags to do that.


It's all good, I have too much karma anyway.

The thing is, there's a difference between a true subset and "some flags that reject certain things." Because that creates a number of different sets that may relate to each other in a variety of ways, some subsets, some overlapping.

But beyond the specific definitions here, "profiles" is that sort of approach, so something like it will happen, probably. It seems to have a lot of support.


"Subset language" is already an option. The developer can choose a safe(r) subset of C++ to constrain themselves to. Many (most?) C++ shops already do this, and go to varying lengths to enforce that only their blessed subset is used. We don't really need a committee to create a new "subset language" to accomplish this.


C++ already passed that line with C++17 and newer iterations. Not only it evolves way faster starting with C++17, the modern code looks sufficiently different that it needs relearning some parts of C++ from start.

I've written my biggest project with C++11, and C++14 was just out back then. Now, I plan to reimplement that project (and improve it), again with C++, but I need to look at so-called "modern C++" to do it correctly and in a more future-proof way.

...and I'm glad I have to do that, because while I love (old school) C++, seeing it evolve makes me happy. Because systems evolve, software scale evolve, and most importantly hardware and ways to get maximum performance from it evolve.

There's no need to write old-school C++ anymore. All these features are developed for a reason, they shall be used.


What new scientific applications are being written in Fortran?


Fluid dynamics codes are still being written in Fortran.

Notably, there are still improvements happening in the Fortran space, and there's been a bit of revival of sorts. There are still features in Fortran that make it nicer to write in than C++ (and while I'd hoped rust might be a good Fortran replacement, I feel rust has taken a different path, and remains no better than C++).


New CFD codes? Links?


I would like to echo this sentiment. I like Rust, but I can't see a Rust monoculture.

From my experience, Rust is an absolute improvement in developer experience around so many corners. I'm looking forward to the future where Rust is well established and boring, and all its round edges have been solved, even if that means adopting another new and exciting language :)


IMO there was only a brief period of monoculture, and only if you consider C & C++ to be part of the same culture, which is a stretch. It started in the mid-80s when people stopped writing programs in Pascal and/or assembly, and stopped in the mid-90s when Java & Perl started to get used extensively.


> if you consider C & C++ to be part of the same culture, which is a stretch

That’s my main gripe with most pro-Rust comments of this kind, to be honest. There are a few ways to write C and a lot of ways to write C++, and most of the C is quite unlike most of the C++. (I’m not counting marginal cases like raw GObject or raw COM as C here, I think those count as basically separate languages.)

The problem is, the Rust I’ve read (and read about) is methodologically and stylistically a replacement for most of the C++, but not a lot of the C. I don’t dislike the theory behind Rust—I’ve written Haskell, I’ve written SML, I read the Tofte&Talpin regions paper and some of the subsequent research more than a decade ago. I do dislike when people ask me to switch or even try to, of all things, shame me into switching from C to what presents itself as a better C++, in largely the same way that I dislike attempts to switch to C++ that claim it’s the same thing as C. No it isn’t. And I largely tune out when I read “C/C++”, because it implies the author does not get it.

(I’m aware there are other people that do get it, some of whom work on other programming languages. They just don’t write posts proposing Rust replace C.)


I was talking about a monoculture specifically in the systems programming area. Java, Perl, PhP, Python, Ruby, JavaScript, C#, Go, these got popular but they use garbage collection and have limitations for systems programming. C and C++ were the only options for a long while.


Systems programming is just a niche. A large niche, but just a niche. But between when Pascal & Assembly stopped being used widely and before Java started being used widely C & C++ were used for pretty much everything.


FWIW it was LLVM that catalyzed the modern florescence of programming language innovation. Rust is just another result of that shift, not its cause.


The author makes the best argument for Rust in the linked post[0]

    Rust is great for teams because it removes many things that make working on team code dangerous. The items mentioned above are some.

    I work alone, however, because I like to keep my code in my head and working with people means parts of the code are only in their head.

    This also means that the bigger the language is, the less space I have in my head for the code.

    Rust is too big for my small brain, unfortunately.
Most code is written in teams and even software with a single author needs a plan for when the maintainer steps down. Besides this I disagree with the author's assertion that Rust is not well suited for them, in fact I think it's strictly better than C because it often obviates the need to keep stuff in your head. Take lifetimes, in C you have to keep track of pointers and their lifetime in your head, and by definition all other maintainers have to do the same, in Rust the compiler does that for you, less to keep in your head. In fact I think the ability offload things from your head to the compiler is one of Rust's great strength. This ties in with compile times too, yes Rust is very slow to compile, but the compiler also does a whole lot more work than the C compiler. Obviously we want rustc to be as fast as possible given the work it's doing, but it will never be as fast as a C or Go compiler.

0: https://gavinhoward.com/2023/02/why-i-use-c-when-i-believe-i...


"Most code is written in teams and even software with a single author needs a plan for when the maintainer steps down."

I strongly disagree! My experience is this:

1. Sole developer builds useful thing

2. Team takes over maintenance

3. Feature bloat, sluggishness, bugs ignored, Agile initiative, "Product owners"

4. Company goes bankrupt or gets acquired

I don't think you can have the clarity of vision that a single person will produce if you're working on it with a big team. That's why so many useful things start with a single person or a very small team, like Linux, Android, curl, ffmpeg, Quake engine, the 2 ppl Firefox "Phoenix" team, the original 3 ppl JetBrains team, the 2 original Photoshop devs.


> That's why so many useful things start with a single person or *a very small team*,

You subtly shifted the goal posts here. But even if you start out with a single person you eventually have to have new maintainers, if only because of human mortality. Software is a young field so we haven't had to contend much with this fact yet, but it's inevitable.

Personally I think something like Rust is helpful for large solo programs too, keeping everything in your head past 10kCLOC is hard so why not have a language and compiler that helps you?


My personal opinion is that Rust is a bit too lengthy to keep everything in your head. For a solo program, I'd probably go with Python first, just because it tends to produce very short and yet readable source code.

And yes, I shifted the goal post a bit by assuming the team to be medium to large in size. If I assume a very small team like the initial Photoshop release with 2 people closely working together every day, then I think their communication will be so good that there aren't "many things that make working on team code dangerous" left. So in that case, I wouldn't expect much benefit from using Rust.


> My personal opinion is that Rust is a bit too lengthy to keep everything in your head

I'm curious what you mean by "lengthy" here. The reason I say Rust lets me keep fewer things in my head is because something like this in C:

    struct Bar {};
    
    struct Foo {
        struct Bar *bar;
    };
where it's no clear if Foo owns Bar or merely outlives it, becomes

    struct Bar;
    struct Foo<'b> {
        bar: &'b Bar,
    }
in Rust and I no longer have to keep this information in my head.


Interesting, it's mostly concepts and architecture in my head, and less lines of code.


Ugh, seen this pattern happen many times at smallish companies. The O.G. codebase was written by a single person. It did one or two things very well, with few bugs, had consistent filenames, variable names, APIs, formatting, and so on, it had a single, pure vision throughout the code, and didn't have all those problems that happen when multiple people reason differently about the same code.

Then, eventually, the company gets bigger and the product needs to grow beyond the capability of one person, so a team starts developing on the codebase. That's where the bugs start pouring in, where everything becomes less consistent, where different design patterns are used all over the place, and where the "single clear vision" gets cast aside. A lot of problems that get blamed on "technical debt" and "brittle code" are often just plain coordination and consistency problems that are happening because multiple people can't share a single consciousness.


Rust is certainly not the last word in systems programming languages, but it's an huge leap forward from C and C++. To be honest, it's a sad reflection of our industry that it's taken this long to get basic safety + ML circa 1975 language features into this niche. If things had turned out a little bit different we could all have been using OCaml for the past few decades.


My favorite hypothesis here is that programming language enthusiasts are too different. They are incapable of convincing the average programmer of the merits of their favorite language, because their way of thinking is different. Arguments they find convincing are not convincing to the average programmer.

Progress happens incrementally with small steps. Existing languages get new features. New languages get popular, because they look familiar but contain some small meaningful improvements. And familiarity is important. Languages like OCaml never become popular, because they are too different. Even the syntax looks unfamiliar.


> Arguments they find convincing are not convincing to the average programmer

I think one problem is believing there exists an "average programmer". It's easy to think in averages (or medians), but the reality is that there is no average person, and exactly one median person.

Realizing that every single person is different is important, because you then start to work in more discrete niches. It's going to be much easier to appeal to "programmers who write X in Y with the following constraints" than it will ever be "programmers who write in Y".

Or to bring this closer to the topic of discussion, you'll never convince game developers to drop C++ in favor of rust using the same arguments as you'd use to convince a service developer to drop C++ for rust.


I agree, though a big issue is that at some points progress can't happen without breaking backwards-compatibility. If the problem to be solved is that something is allowed which shouldn't be, then backwards-compatibility will prevent progress.

C & C++ allow quite a few things they shouldn't need to allow to accomplish their goals. They'll never stop allowing those things, so they'll never improve in certain ways.

Rust has a strong backwards-compatibility guarantee, and it has run into this issue with its standard library already. The edition system means the language can break compatibility in some cases, but the standard library can't. I suspect this will eventually prevent necessary incremental change, as it has for C & C++.


> Existing languages get new features

That's how you wind up with C++


Or English.

A lot of people used to advocate for using their favorite ancient / artificial languages in international contexts and for communicating important matters. But somehow the C++ of natural languages became dominant.


I think you're right. The same way people have strong preference for Systemd, MacOS, KDE, Gnome, I3, Nix, Debian, Gentoo, Arch, etc.

So many different solutions. Most are preferred because of subjective reasons (although sometimes just poor reasoning period), because people think so drastically differently.


People reject OCaml for these use cases due to the GC, but I wonder if this actually matters in practice. The optimizations that can be applied to ML languages (see MLTon for example) are very advanced and the ability to do multi core with ease (I know this is more recent to OCaml) can be a big performance unlock that is very hard to get right in C.


The GC does matter.

Most applications are completely fine with having a garbage collector, but they are not fine with having multiple garbage collectors! Mixing multiple garbage collected languages is a recipe for complex bugs. At a minimum, reference cycles across the languages will result in memory leaks.

Thus every garbage collected language tends to grow its own ecosystem of libraries, with the whole world having to be re-implemented in that language. The only exception are the C/C++/Rust libraries, as these can be used (through C FFI interface) by almost every other language. This is precisely because these languages do not introduce their own heavy-weight runtime (especially: no GC), allowing them to be combined with another language's runtime.

Thus widely used libraries must be written in one of the non-GC languages, even if 100% of the applications using them are fine with having a garage collector.


I see this same situation playing out with async executors. tokio is taking over, but it doesn't play well with other async executors. I just wrote a program that mixed tokio & glib and it wasn't fun.

This does feel like a soluble problem, so I hope they do figure it out. I think the first step might be something like without.boats' proposal to add something like https://github.com/zesterer/pollster to the standard library to establish a minimum common denominator.


GC is perfectly fine for ~99% of applications, which is why all the languages in the last few decades adopted it, and eliminated themselves from being direct C/C++ competitors.

Lack of GC isn't a requirement for most programs. However, it is a requirement for a language meant to actually replace C and C++, because these two are mostly used in the remaining fraction of programs and libraries where any GC or any fat runtime is undesirable. Even where some GC could be made to work, it makes it a tough sell for C/C++ users.


> it's a sad reflection of our industry that it's taken this long to get basic safety + ML circa 1975 language features into this niche.

That's true. Could it be that's because we are expert at nitpicking every programming language, every framework and stack which appears to the point it takes time to make steps forward ? Some sort of paralysis, insecurity and confusion ?


Sadly, Rust is only a "huge leap forward from C and C++" for some use-cases.

Simple things like returning a const reference to a slot in an immutable array are easily 10x the amount of source code in Rust when compared to C. And all the standard libraries for embedded systems are C, so to get into embedded development, you definitely need to be good at reading C code. Rust is an additional skill, but if you only know Rust and no C, you're of no use in embedded land.

I think that's the main reason why we don't move away from C: You still need a firm grasp of C if you want to be a capable higher-level developer.

C++ is then the logical upgrade because it's compatible with C and looks very similar. Java also did OK because it looks and feels very similar. And there's good automated C to Java converters. So you get the benefits of Java over C almost for free. Rust, on the other hand, throws away most of the C conventions and that makes it feel foreign and "incompatible".

Rust also suffers from a serious "not invented here" problem, in my opinion. It's super easy to re-use C code in C++ or Java. It's significantly more difficult to re-use C in Rust unless you go unsafe and abandon most of the Rust advantages. That means most dependencies need to be re-implemented in Rust if you want to have all the advantages that Rust offers. Go had the same problem, but they had Google's weight behind them to push out tons of libraries. Who is doing that for Rust?

In the end, I agree with the article: Rust is great! when it fits. But there are still plenty of situations left where Rust is worse than old-school C.


> Rust also suffers from a serious "not invented here" problem, in my opinion. It's super easy to re-use C code in C++ or Java. It's significantly more difficult to re-use C in Rust ...

It feels like a mischaracterization of Rust and I strongly disagree. Both the language and tooling are designed from the beginning for interop with C code. It isn't very hard to do if you have tried it.

> ... unless you go unsafe and abandon most of the Rust advantages. That means most dependencies need to be re-implemented in Rust if you want to have all the advantages that Rust offers.

This 'Rust is useless if you use unsafe' is a stance that is well debunked, but still gets repeated like this. Ensuring safety using Rust semantics across an FFI with a language like C is impossible - making unsafe necessary. But just because you use unsafe doesn't mean that the language lost most of its advantages. In fact, almost every Rust program uses unsafe code, if you care to look at the code in the standard library. Yet, that never seems to be a problem.

What unsafe does is to cordon off a small code area where certain invariants have to be asserted manually, instead of relying on the borrow checker. You still get the safety for the rest of the code. In case you do get safety violations, there is much less code to debug. This is a significant advantage over languages like C++, considering that unsafe blocks are usually less than 5% of the code, even in the worst case. But to take it further, C libraries often have corresponding Rust wrapper libraries that create safe wrappers over C FFI calls. In addition to the small unsafe blocks to verify manually, these wrappers have the additional advantage of being widely used and debugged by a wider community. There are innumerable such wrappers on crates.io and it's uncharitable to accuse the language of NIH syndrome.


"It isn't very hard to do if you have tried it."

My attempt at OpenGL rendering with Rust turned out to be a lengthy journey of suffering through way too many layers of rust wrappers around unsafe C shared libraries. I especially hated that I constantly had to use casting helper functions to go from pre-defined OpenGL constants back to their associated integer values.

And I do think it's valid to accuse NIH syndrome if there is exactly 1 OpenGL API in C but there are 100+ Rust crates for various OpenGL wrappers.


> My attempt at OpenGL rendering with Rust turned out to be a lengthy journey of suffering through way too many layers of rust wrappers around unsafe C shared libraries. I especially hated that I constantly had to use casting helper functions to go from pre-defined OpenGL constants back to their associated integer values.

From this description, I can't figure out if you used FFI or a wrapper library. But it looks like you are complaining about both - which can't happen together. And the problems you mention seems very specific to the choices you made. I have faced similar problems with other code - something often solved by choosing a different library or approach. I don't see that affecting Rust's FFI story.

> And I do think it's valid to accuse NIH syndrome if there is exactly 1 OpenGL API in C but there are 100+ Rust crates for various OpenGL wrappers.

By definition, they didn't invent anything if the crates were wrappers. They were just using that exactly 1 OpenGL API - the thing that you were accusing them of not doing. And as for 100+ Rust crates, I don't think that should be a problem. Wrapper developers often try different API styles. It's just that crates.io makes them all very visible. In practice, just one crate (or a group of related crates) become popular enough to be the defacto standard in a segment.


> It's significantly more difficult to re-use C

It's not, and you're over indexing on your experience with OpenGL.

There are plenty of rust libs that are thing wrappers over C libraries. They're widely used, without a problem. libgit2, written in C, is the most popular Rust library for git bindings.

Despite that, people do prefer pure Rust libraries for a very valid reason - it makes building the project, especially cross-compiling very easy. That's why cargo audit shifted from libgit2 to gitoxide.

Who is sponsoring the development of these libraries? The Rust Foundation gave the developer of gitoxide grants to develop it, with the eventual goal of replacing libgit2 in cargo.

I'm sorry you had a bad experience with OpenGL, but I don't think it's accurate to extrapolate your experience with that onto the entire ecosystem.


> Simple things like returning a const reference to a slot in an immutable array are easily 10x the amount of source code in Rust when compared to C.

I’m very interested in what you mean here. Isn’t the syntax identical in both cases?

  &array[index]


My personal take on this subject is that Rust turns experts back into beginners and some devs react with hatred because of the fear this induces. For me it was the opposite. I was getting bored with my industry and thinking of a move to something else like management. Rust came along 6 yeas ago (for me) and threw me a lifeline. I love getting good at something that is hard, it’s just very satisfying. I do get why some people can’t stand the language. It is ugly to look at with its genetics and lifetime annotations and when a project is so large that it begins to lag rust-analyser then my joy turns to rage too.


> My personal take on this subject is that Rust turns experts back into beginners and some devs react with hatred because of the fear this induces.

Those people are probably poor devs. Anyone who doesn't have the attitude and mindset to continue learning in something like software development which keeps advancing isn't cut out for that field.


Maybe it wouldn't be reasonable to say this about people who dislike programming in Malbolge, and maybe there are aspects of Rust that are more like programming in Malbolge and less like the field advancing.


You could have spend that time learning something which is actually useful and helps finding interesting jobs. For example, GPU programming or SIMD intrinsics.

What annoys me about rust is the complexity just for the sake of it, lots of pain for minimal gain compared to alternatives. If you need async/await you'll do better in modern .NET despite the GC, if you need the highest CPU performance you'll do better in C++ despite the unsafety.


"despite the GC" and "despite the unsafety" is really putting a lot of weight on that "despite"

These are massive problems


I don't think it's so cut and dry. For lots of usecases, using Rust involves writing everything from scratch, because the only libraries available pull in an opinionated async runtime and feel entitled to call the global allocator and various syscalls at times the user cannot control, and these components cannot be swapped out because of fundamental issues that prevent Rust libraries from being composable (unless they go out of their way to adopt a feature that launched late last year?). IME there are relatively few usecases where long stalls due to GC are bad but long stalls due to page faults or open(2) taking a couple seconds to return are fine.


You're replying to me as if the comment was in a vacuum

It's responding to:

> complexity just for the sake of it,

> lots of pain for minimal gain

> If you need async/await you'll do better in modern .NET despite the GC

> if you need the highest CPU performance you'll do better in C++ despite the unsafety

To this I respond, GC is such a massive problem (I guess you can fill in "for some categories of problems" but I think it's obvious) that some people need to avoid it. And those people often turn to C++, where the "unsafety" is a very big problem.


I don't think so? My reply is that if you can't afford to stall for a really long time, like dozens of frames at 60hz at least, then your choices are often to deal with unsafety in C++, to deal with the GC in .NET, or to write everything from scratch in Rust (including many things for which you would typically use libraries) because idiomatic Rust and the associated ecosystem won't solve your tail latency issues. The last option is not obviously more attractive than the approach of working really hard to not make garbage that Unity devs are usually forced into after years of development when they start testing on Switch.


You can deal with that in .NET the "C++" way too, given that you can write abstractions with structs and generics instead of objects, use malloc and stackalloc, and more. You are not married to GC heap, despite some suggesting otherwise.

Generally speaking 60hz is not a problem but it starts to matter more with the popularity of high refresh rates. There are much more extreme cases like 1000hz game loop in OSU!, which pretty much has to use the same techniques as realtime systems that utilize GC-based language: https://github.com/dotnet/runtime/issues/96213#issuecomment-...


That depends a lot on the domain of the code.. just saying they are massive problems is plain wrong. There is a huge percentage of applications that need not care about GC at all.


>the syntax. It’s ugly. [...] I would prefer something that is less sigil-heavy.

That's also one of my gripes with Rust. Very sigil heavy makes it hard to google syntax elements. What's the name of the `|` glyph? Especially challenging if you know the name of the glyphs in your language but not in necessarily in english. Double challenging for glyphs with several accepted names

But in the end, I'm big enough to realize that this is not a very important aspect of the language

If it's ugly so be it. I'll still learn it

Also for once Bing Copilot pretty much solved this for me since unlike google search, it's semantic + it doesn't ignore special characters


FYI Wikipedia has pages for every ascii character I think, if you just search for `|` in wikipedia it would redirect you to

https://en.wikipedia.org/wiki/Vertical_bar

Which lists all the common names used for this symbol

Here is also a table with all symbols with direct links to the wikipedia pages

https://en.wikipedia.org/wiki/ASCII#Character_set



That doesn't seem to explain 'lifetimes or turbo::<Fish>, though.


The page linked for :: explains the turbofish.

That said, you're right that it could use a row for the lifetime syntax.


If you know where to look, you will find it. If you don't, you don't.

For someone new to Rust, I don't see why you'd expect them to expect to see a "path separator" between the function name and it's call in x.collect::<Vec<_>>(). A more likely path to discovery is via the Generics link (discovered from "<" being so prominent there), which shows the ::<> syntax in context of const values, and that isn't actually very helpful for understanding.


So the thing is, the link provided is not really intended to be "teach me what syntax means." It is meant to provide a reference for various tokens. And it does that, because the turbofish isn't a single thing, it's a combination of two things.

If the goal of this page was "comprehensively explain Rust syntax to someone who doesn't know Rust," I would agree with you. But it's "produce a spec-like document for experts who want fine-grained details about the language."


I just cloned the Starship repo and cargo --release built it and it took six minutes and 30 seconds (which did feel interminable). The author says it takes him 15 minutes "for building just the main.rs", 10 minutes for "lib.rs" and an unspecified time for "everything else".

My CPU is from 2012. What on earth is he doing this on, a TI-83? Or am I missing some intricacy of whatever Gentoo is doing that would inherently inflate build times by an order of magnitude?


> The author says it takes him 15 minutes "for building just the main.rs", 10 minutes for "lib.rs" and an unspecified time for "everything else".

That's weird, cargo displays the current crates under compilation, not files as that's not the compilation unit in Rust, the author seems to be fibbing.


    $ emerge -v starship
    <...>
    Running `rustc --crate-name starship --edition=2021 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type lib <etc>
    Running `rustc --crate-name starship --edition=2021 src/main.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type bin <etc>
This person is using gentoo, gentoo does print it like that.


Just another data point. I cloned and ran `cargo build --release`. It took 2 mins and 2 seconds (M1 Pro, 2021).

Just want to say, creating a release build is really unusual! You'd do that relatively rarely. Most of the time you'd create a debug build, which took 29.56 seconds on my machine for a clean build and 1.45 seconds for an incremental build with one line changed.

I sympathise with the author's running on underpowered hardware, but it might not reflect the experience of the average Rust developer.


Rust doesn't play quite as nicely with Gentoo's packaging system as C/C++, but yes, that seems excessively long.

Then again, I'm fairly sure I have starship installed via `cargo install`, not via portage (Gentoo's packaging system).

I'm a Rust and Gentoo lover :D


5m 39s here on a 2017 CPU: Intel(R) Pentium(R) CPU G4560T @ 2.90GHz


People complaining about Rust... As Bjarne Stroustrup says: "There are only two kinds of languages: the ones people complain about and the ones nobody uses"

This is actually the kind signal I wanted to see. A language everyone likes isn't right. In production, programmers have to follow customer requirements, not the other way around, and customers don't care about your pretty code, they want their things to work, and at some point it is going to get ugly, and people will complain. As time goes on, there will be more and more of that ugly legacy code, and you have to keep it, because people are using it, and people will complain more, and they will blame everything that relates to it: the language, customers, management, previous devs, etc... It is actually a good thing, it means the language is used to do real work, you will never get these complains when all people do with it are toy projects or a few precise, programmer driven programs.


Worse is better in programming languages. You decide "I'll use python because everyone else uses it" and then you waste a week of your life debugging when some asshole on your team has mutated a dict that you passed into a critical function and you didn't notice.


> First, the syntax. It’s ugly. TO MY EYES!

Beauty is in the eye of the beholder, you can't please everyone and you should not exceed your weirdness budget[1]. The decision to please the C++ crowd so much (mainly manifested in later syntax related decisions) would not have been my preference, but it makes sense and there could have been worse decisions.

> Second, Third, Fourth, Fifth

I feel a lot of this async criticism has more to do with how async is used than with Rust itself. Maybe it would be good to have more crates that don't used async or even depend on tokio, but in the end this is on us as a community.

> Sixth, Rust doesn’t go far enough in static analysis. Rust had a chance to go much further, and the team blew it.

I am not qualified to judge that, but I am curious of other opinions.

> Seventh, Rust compile times are a joke

True, but this is actively tackled on multiple fronts. One is cranelift, which I find highly fascinating.

[1] https://steveklabnik.com/writing/the-language-strangeness-bu...


> I feel a lot of this async criticism has more to do with how async is used than with Rust itself. Maybe it would be good to have more crates that don't used async or even depend on tokio, but in the end this is on us as a community.

No, this is a language design issue. In Lua or Zig the easy way to write a library that speaks websockets produces a library that works with synchronous or asynchronous i/o and with the user's choice of read and write primitives. In Rust, after many years of unnecessary suffering, we finally have the ability to ship one library that can use either kind of i/o.... unless the user wants to use both in the same workspace, in which case they are screwed. You may enjoy this tale of a user trying to get Rust to do what Lua and Zig do by default, for a single library: https://nullderef.com/blog/rust-async-sync/



This looks great! The example in the linked post directly addresses the obvious follow-up of "well, what about for functions that use traits that are currently divided into two or more flavors?". I hope it progresses to an RFC and code sometime!


The post is a bit of a rant and all over the place. Async infecting everything, ugly syntax (who cares?), slow compile times etc.

What stood out to me:

> In other words, if compilation is fast, the tooling is easy.

Andrew Kelley said something similar in a recent talk. Compiler performance seems to be the number one priority at the moment for Zig.

The rationale seems to be: fast compilation leads to more productivity, which leads to more bugfixes.

This claim seems almost bruteish, but it makes sense.

Tight feedback loops (think things like devops, REPL, TDD, light processes etc.) can help us to iterate more and stay in the zone.

To be fair a sophisticated type checker like Rust‘s also helps with that.

But of course any added friction and sluggishness can be an indirect hindrance to the overall correctness and even performance of a program.


Fast compilation is nice and I believe stuff like incremental compilation are essential.

But at the end of the day I'll prefer slower compilation every time if it means advanced checking.

And speaking of the zone I prefer writing Scala code for like 1h while fixing compiler errors and then you run and it just works TM vs Java where you'll waste your time tracking NPE ...


> But at the end of the day I'll prefer slower compilation every time if it means advanced checking.

I don't think that's a large issue in Rust. Type checking is quite fast in comparison to code generation.

Generics, traits, macros etc. seem to be the culprit. Turning complex language features into code and not runtime safety lead to these slow compile times.


> ugly syntax (who cares?)

I'm a nobody of course, but I do. Ugly is subjective, and by "ugly" a lot of people probably think "alien", as not what they are used to. Less syntax cruft is good for cognitive load and more common syntax is good for adoption.

But I'm sure the problem fades away with practice.


> The rationale seems to be: fast compilation leads to more productivity, which leads to more bugfixes.

Sure, but add LLVM to the mix and you get a slow ass compilation time even in Zig (See Zig filing divorce from LLVM https://github.com/ziglang/zig/issues/16270). Granted, LLVM isn't the only thing to blame. Rust has its own share of problems stemming from monomorphisation, and macros, type check seems to be not as big of a culprit. Although, that depends on the project.

Being fast to compile, versus being efficient to optimize seems to be the trade-off here.


> ugly syntax (who cares?)

Code is meant to be read, so a lot of people care actually.

Sure it's not the only thing that contributes to the usefulness and appeal of a language, but reading code is still one of the two main things we do with it so it's quite important to nail the syntax right.


Yes, but readable and beautiful are two very different qualities.

Rust is a wolf in sheep’s clothing. It looks like C syntax but largely expression based like functional languages. It also has a lot of syntax.

It is readable with little effort for most because of it. But the trade off is ugliness.


The post doesn't seem to mention certain parts of the community, which is basically my main issue with Rust.

You can't even mention that bootstrapping the compiler is a process that's way too convoluted, because you get buried to oblivion ("why would you need that"). Thankfully there are some already, though incomplete because (I'm guessing) Rust being mostly defined as "whatever rustc outputs" doesn't help reduce the pain of checking if your implementation is correct. I appreciate the efforts that are going on to write informal non-spec documentation about the language though, better than nothing.

Also can't mention that alternative compilers would be nice (e.g. to make bootstraping easier, see previous point), because you also get buried to oblivion ("don't fragment the ecosystem", "the Rust council/teams/etc will always be composed of trustworthy people now and forever").

Like, yes, but chill a bit and try to consider other use cases instead of reading those topics as attacks to the language just because you think you don't need them. A small minority being very loud in rejecting any attempt at healthy discussion is not good optics for the ecosystem.

This stuff also happens with other languages' communities, but somehow I seem to find them happening a lot more frequently with Rust.

(P.S.: Changing the topic a bit, I'll invoke Cunningham's Law and say there's no easy way to read Rust documentation offline that doesn't require a web browser of some kind or parsing HTML output. Some equivalent to `go doc` or Python's `help()` function.)


> The post doesn't seem to mention certain parts of the community, which is basically my main issue with Rust.

Mine too, but my post implied it, and it was already too ranty.


I'll bite: What specific parts of rust syntax do people find so ugly?

I keep hearing this from decent chunks of people who don't write rust, but the language doesn't seem that far off C to me. It's certainly no haskell.


From what I've asked people, the complaints fall mainly into two categories:

* familiarity and aesthetics. Rust uses fewer round () parens, and more <> and {}. This makes it look alien, and people say it's unreadable when they don't immediately recognize the language constructs they know.

* misattributing difficulty of learning Rust concepts like lifetimes and generics to their syntax. People say they want less syntax, but they mean they don't want to explicitly specify things like ownership and trait bounds.


The more interesting follow up question is: "How would you express the same semantics with a different syntax?" Too often discussions about Rust's ugly syntax lack this crucial component.


> How would you express the same semantics with a different syntax?

This isn't the problem, the problem is "... and keep the syntax C++-like?".


Is it? I don't know if keeping Rust's syntax C++-like is a stated goal of the project, but okay sure we can add that caveat to my question.

The big problem I see is that people will say "Lifetime annotations are ugly and noisy" and when pressed on the issue will eventually concede that they just want GC(which is not about syntax, but semantics)


It was a goal, though lower priority than other goals. You can see this in the way Rust is largely “curly braces and semicolons” but at times when there’s good reasons it diverged from that, like the ML style let syntax.


> I don't know if keeping Rust's syntax C++-like is a stated goal of the project

They won't change the syntax, the whole discussion is hypothetically anyway. What I wanted to express is that most people want a C++-style syntax (of generics), even if they complain about Rust's syntax.


I say this as a Rust enjoyer, but I think what most people mean when they say this is that there's a lot going on, especially in the function definition syntax. When you start adding in lifetimes and generics with bounds, async, &muts, where clauses... it really does become unreadable. I don't really see a way to fix this without making the syntax even more verbose, or aggressively simplifying the type system to the point that function argument inference becomes viable, but then you might end up in a situation like Swift's where type checking a simple expression takes an excessively long time.

That and the colon-colons (::), probably. Those can add a lot of noise.


I suspect the colon-colons were a mistake. Java uses periods for both modules and classes, and it doesn't seem to be a problem there.

Lifetimes are really ugly. You usually don't need to write them explicitly, but that's not a real excuse.


> colon-colons

I prefer "quad-dot". Rolls off the tongue better. :)


https://web.archive.org/web/20230713231438/http://bash.org/?...

  < Andys> oh dear
  < Andys> in ruby, symbols are represented with a prepended colon
  < Andys> eg.   :flag
  < Andys> so some guy tshirt that said ":sex"
  < Andys> which everyone at railscamp knew meant "Sex symbol"
  < Andys> he wore it until someone pointed out that to non-rubyists it said "Colon sex"



I think it's not that much the specific parts as it is the combination of (sometimes obscure) symbols forming dense blocks of sigils that you have to carefully pick apart to understand what the code is doing. It's easier to reason about code if it uses words instead of symbols, and Rust seems to desperately want to avoid using actual words (I don't count "fn" as a word, and "pub" is a word, but for me it's somewhere where you go to have a drink after work). Ok, I know there is a long tradition of doing this in C-family languages, but Rust has driven it to new heights, and it has a lot more concepts (with their attached symbols) that you have to keep in your head.


I hate the unpronounceable sigils of languages like Haskell, but C-style abbreviations don't really bother me somehow. The abbreviations help you remember what the words are, at least, and for me this seems to be enough.


>I keep hearing this from decent chunks of people who don't write rust

That's exactly the people you want to hear from if you're trying to improve adoption.


Here's my litmus test: read the source aloud. Over the phone to a person who doesn't see your screen, if needed. Did you have an obvious, understandable, and simple pronunciation for everything, that wasn't just reading ASCII characters one by one?

Now pretend the other person is a smart and experienced programmer, but has never heard of Rust. How would they write down what you just told them, without any idea of Rust's syntax? That's the non-ugly version of Rust.


    function max with type parameter T
    with arguments
    a of type T and b of type T
    and returns a value of type T
    where T implements trait PartialEq
Vs

    fn max<T>(a: T, b: T) -> T where T: PartialEq


Limiting examples to a subset of Rust syntax will produce more readable answers, sure. You have no lifetimes and no borrows, and very limited generics.


The information density of the "human syntax" Rust syntax both remain linear in size, but with a significant different N.

    function max
    with
        a lifetime a,
        a lifetime b,
        and type parameter T
    with
        argument a of a reference to type T that lives as long as lifetime a
        argument b of a reference to type T that lives as long as lifetime b
    and returns a value of type parameter T
    where T implements trait PartialEq
Vs

    fn max<'a, 'b, T: PartialEq>(a: &'a T, b: &'b T) -> T

If you want a real life example:

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a, T, A: Allocator> IntoIterator for &'a Vec<T, A> {
        type Item = &'a T;
        type IntoIter = slice::Iter<'a, T>;

        fn into_iter(self) -> Self::IntoIter {
            self.iter()
        }
    }


    An implementation of trait IntoIterator
    (that has been stable since Rust 1.0.0)
    with a lifetime a
        a type parameter T
        a type parameter A which implements the trait Allocator
    for a borrow for the duration of lifetime a of type Vec with type parameters T and A
    
        it has an associated type Item, which is a borrow for the duration of lifetime a of type T
        it has an associated type IntoIter, which is type Iter from module slice with parameters lifetime a and type T

        it has a method into_iter
            that consumes the receiver
            and returns associated type IntoIter
            
            the methods body
            calls method iter on the receiver
            and returns its resulting value


I'm not arguing that complex things will somehow become non-complex.

However, none of the human syntax of Rust includes things like :: or '. To a first approximation[1], those are the parts that people can experience as "ugly", and they are not present in the human syntax. This is what people mean when they say "sigil heavy" or "punctuation based" syntax -- things that are generally are not read out as such. This is the space where you can make arguments about beauty.

[1]: Only roughly so because your chosen human syntax still encodes some Rust syntax decisions like predeclaring generic lifetimes and types, and using "where" instead of an inline clause. Those parts of syntax can also be shuffled around for subjective values of "not ugly".


Lifetime bounds on a trait object argument can be confusing.

I have to look up how to write the where part properly every single time.


Fishtail, lifetime and closure syntaxes are rather ugly. Just specifically when combined in practice, not alone in isolated examples.


For what is worth, the turbo fish falls from the decision to use <> for generics (for familiarity for C++ and Java developers) and a desire to make the syntax non-ambiguous (side stepping the C++ problem of having to delay determining if something is a type path or a comparison, mixing parsing and name resolution).


> What specific parts of rust syntax do people find so ugly? ... the language doesn't seem that far off C to me. It's certainly no haskell.

Make that "not far off C++" (C is really beautiful in comparison), and there's your answer.


This argument is always so divided into very thoroughly mine-protected trenches it’s insane.

The anti-rust crowd treat the language like it has more boilerplate than JavaScript and that it’s the most complex language out there while offering no benefits, which just isn’t true. It’s a great language with a lot of features that are huge advantages over C/C++.

The rust evangelists treat it like it’s the second coming and that you’re literally killing babies if you aren’t letting the language enforce its paradigms on you. The forced safety the language offers is a great feature in 2024, but it is not a be all end all thing - there are plenty places where it just isn’t necessary and creates more work for the programmer. The argument is also usually “everything should be rust” but the moment you point out a use case where its advantages don’t matter, they say “well the rewrites only need to happen for <x critical direct networked service>” - that then means everything doesn’t need to be rust, no?

Like most things, the correct path is somewhere in the middle. I personally don’t like Rust’s syntax, generics, not being object oriented, etc - but that’s just my opinion and is no more valid or invalid than the next. At the end of the day, use the language you like most and are comfortable with, as long as you understand the benefits and drawbacks of each.

- Signed, a Kotlin evangelist


Within Rust is a smaller, simpler, safer language struggling to get out


Without a GC? No there is not. You are welcome to try of course, but unless you have a PhD in type theory I doubt your chances.


Author here.

Yao is already fully designed. And while I haven't updated its example file [1] to include everything, it would only be a max of two or three times bigger.

This includes generics, an equivalent to Zig comptime, something like traits but more powerful, a solution to the expression problem, etc.

The solution is structured concurrency.

The only reason I am not working more on Yao is because I worked on it for three years at full tilt (because I constantly refactor to eliminate tech debt), and I am burned out.

But adding a new feature takes only about two hours max; I just add a new client-defined keyword.

[1]: https://git.yzena.com/Yzena/Yc/src/branch/master/src/yao/exa...


There's a smaller, simpler, safer language lying in Rust called "Rust without async", which would be good enough for the 99% of use-cases that don't need absolute-lowest-possible-latency async.


No one is forcing anyone to use async though. It is an entirely optional part of the language.

But it is naive to think that not using it is an easier path towards a solution.


YMMV, but Austral-lang (https://austral-lang.org/) comes quite close to what I want out of a smaller, simpler, safer Rust.

Its syntax is inspired by Ada, and as far as I know the designer has no PhD in type theory, so it matches the requirements put forth by the other commenters too.


Readable would be a nice benefit.


Not sure about smaller or simpler, but Ada is definitely more readable in my opinion.


This, I don't understand why we have to load these languages up with so much syntax, it's mind boggling to think that some how we feel it's beneficial to have so much. I'm admittedly biased to the symbolic expression but surely we could have come up with some middle ground.


Two things:

- It was made to be approachable for C++ experts

- The idea was that language could be effortlessly greppable.


Coming from C++, and I would have loved Rust to not pick up C++-y things to make it look like it...


So legacy baggage from the get go. This is what I'm lamenting, it's objectively a syntax soup.


This is my current mental model for picking a language, considering just the language itself:

- Backends: Gleam or other BEAM

- Web frontend: Gleam

- Mobile apps: Dart + Flutter

- Specialized mobile apps: Swift and Kotlin

- Blazing fast: Zig

- Blazing fast and safest: Rust

- Fast performance and iteration: Go

Would love to hear additions and corrections.

My only problem with this is I'm not a fan of Go's syntax and I wonder what's a good alternative. Heared good things about OCaml but didn't check it out yet.


OCaml could almost replace all of those. I don’t think there is a BEAM compiler backend yet.

I’m not very experienced with BEAM, but could its features be delivered with a framework on top of a different stack? I know Akka is popular.


The OCaml backend for the BEAM was called Caramel but has been abandoned after his author went on working on hiw own build system, warp.


Build systems come for our best and brightest. :-(

Talk to your friends and family.


Actor model is a small component of the BEAM. Even then, it guarantees yields to the scheduler.

This is practically impossible to retrofit on to an existing language, esp. in the presence of loops.


GC precludes OCaml from replacing a chunk of those.


>>> don’t think there is a BEAM compiler backend yet

I think there's something close - https://caramel.run/manual/


The project has been abandonned : https://github.com/leostera/caramel/discussions/102


I’m super into elixir now and don’t see myself going anywhere else. Is gleam really that good? What are the advantages? Can I use liveview with it?


As far as I know Gleam is the only strongly typed language on BEAM, which is important to me since I don't like dynamically typed languages. But of course Elixir gets optional types now.


There is also:

Purerl - Erlang backend for PureScript, a few folks are using this in production - https://github.com/purerl/purerl

Caramel - Ocaml for Beam, seems dead - https://github.com/leostera/caramel

and more probably dead projects at https://github.com/llaisdy/beam_languages


Is that the only difference?


It can also compile to JavaScript (instead of the BEAM) so you can use the same language for backend and frontend work.


- Backends: Kotlin (on JVM)

- Web frontend: TypeScript (maybe Gleam in the future!?)

- Fast performance and iteration if I want a binary: Kotlin (native compiled)

- Blazingly fast and good for WASM: Rust

- languages that I keep an eye on: Gleam, Zig, Odin

- languages that I will never touch: C, C++

- languages that I think are quaint: OCamel, Lisp, Haskel

- languages that I have used in the past and that are fine: Dart

- languages that I have used in the past and that are ok: Java (if it had nullability, it'd be fine)


I love Kotlin, but don't want to use IntelliJ, and they obviously have strong financial incentives against supporting other IDEs. Has anything changed in this regard?

I appreciate their work on native/wasm, and I think it's great if they could be financially rewarded/sponsored for that work. It's just unfortunate that it has to be in the shape of an IDE dependency.


Nim fits a lot of Go's use cases. It is way more niche though.


I have seen a lot of criticism of async Rust.

In C# most APIs expose both sync and async versions of the same methods. Why is that not more common in Rust?

Sure some 3rd party C# libraries probably do some ugly sync to async conversion internally but most don't and use the .NET standard libraries sync/async versions of the same APIs.


Rust's async is in some places more difficult to use, because Rust is obsessed with avoiding allocations and dynamic dispatch.

Languages like C# and JS allocate a new object for every Promise and every listener. Rust bends backwards to avoid that, and make inlined strongly typed state machines instead. It creates limitations where you wouldn't expect, e.g. recursive calls need special handling, and abstract interfaces don't fully support async.

As for supporting both, it's just inconvenient to do, because many small syntactic and semantic differences mean it's hard to automate and cumbersome to maintain.


Not every await and new task produces an allocation in C#: ValueTask only allocates a state machine box if it yields asynchronously, plain task objects are pooled for common values and state machine box itself can also be pooled for frequently called methods (is opt-in), for example socket.SendAsync does not allocate thanks to this.

This will change further as "Runtime Handled Tasks" implementation comes along which will replace Roslyn-generated explicit state-machine code with runtime-provided suspension mechanism which will only yield/suspend the execution at true yield points, with further improvements to how the captured state that needs to persist across them is stored.


Maybe that will sound banal to some but C would be so much more enjoyable to me if it had a "cargo" system and no implicit imports.


That's the problem with C. It cannot have a sane cargo like system. The language is not built for writing libraries. There is a reason why everyone keeps reinventing the wheel when it comes to datastructures in C. Where is STL for C?


The closest is GLib and it's absolutely not fun to work with.


you could use the Zig build system as your C build system. See https://zig.news/kristoff/make-zig-your-c-c-build-system-28g...


Cargo is just half the story. The other half is rust itself. It is an excellent language for writing abstractions.


That's why i like zig it has at least the very basic with build.zig for build script. You have build.zig.zon for build.zig dependencies.


I mostly agree. Compile times are the worst in the industry, and async is a mess.


Rust is a systems programming language. It forces you to think about computer architecture as you are writing code. The language is a tool expressing how logic should execute safely and performantly on actual hardware. That is both its strength and weakness.

I agree with the article in so far as the hope that people will not start pushing Rust as the cool language for pretty much everything.

For many development endeavors, the language is a tool purely for expressing logic, and for that Rust is a poor choice IMO.


What does Yao look like? edit ah I found some examples https://rigbuild.dev/yao-tutorial/


You can also look at the example file.

[1]: https://git.yzena.com/Yzena/Yc/src/branch/master/src/yao/exa...


"I like small programs with few dependencies. I will write my own I/O to avoid dependencies. And tokio is to dependencies what god objects are to object-oriented programming."

This is what is preventing me from using Rust. It is so tightly integrated with a package manager for libraries that trying to avoid crates.io and dependencies is like paddling against the current.


@gavinhoward Just FYI, a couple of links in the article are broken:

* The "incomplete list" of C UB currently points to the Rust spec vision

* The link labelled "unreasonable programming language" currently points to the Gentoo Wikipedia page

* The "Starship" link points to the House Wiki page on Vicodin


Ack! That is what I get for writing a post quickly while drunk on sleep fatigue late at night.

And the rantiness comes as a side effect of that.

Fixed, Thank you!


The compile times are the only real issue mentioned here.

I still think it's better than C++ but for large projects the compile times and crate splitting, etc. become a real pain.


Not to author: The URL for the "incomplete list" hyperlink is incorrect.


Ack! Thank you, fixed.


A lot of this author's complaints about Rust remind me of similar historical complaints about C++, but amplified.

Hijacking and overtaking new projects? C++ and Rust both do that. C++'s compile times were a joke, Rust is even worse. Complex semantics and syntax? Both have those. Rust is trying to be everything to everyone? C++ has always been criticised as design by committee.

And yet C still exists and is widely used. Once the smoke cleared, people simply hated C++ and what it brought. After all was said and done, C became regarded as much more tolerable and usable for lack of those headaches. C++ still exists and there is certainly not a C++ monoculture. I hope and expect that the same story will play out for Rust.


Do you mean that once the Rust smoke clears, people will see C++ as much more tolerable and usable? :')


What are some examples of the complex semantics? The things I can think of(lifetimes, generics, traits) exist and are modelled in C too, but just with less(or no) support from the language and compiler.


Projects adopting rust makes contributing less fun and more painful

I tried to work on bug fix for Zed, waiting 30 seconds everytime you change a value was _very_ painful


At least, compiling is always straightforward. With C, there's a good chance the build will fail for whatever reason (e.g. your OS missing some header files).


Yep, IME rust makes contribution easier because I generally don’t need to hunt for setup instructions which may or may not exist and may or may not work for my system.

And the compiler at least attempts to tell me what’s wrong when it fails to compile (and give suggestion though that is very hit or miss for non trivial case).

The one case where the compiler is singularly unhelpful is when trying to hunt down why a future is !Send tho.


I feel like you could stand to qualify "fun" more here. I don't share your experience - I'll take a Rust project any day - but I'm curious to know what you feel is missing.

(Outside of compile times, which are a well known point)


There’s no reason you couldn’t have a rust jit for development then compile the code for production (or stick with a jit for prod too).


There's no reason? Are you sure about this?

I think you mean there could theoretically be an interpreted Rust, but I don't think anyone has ever made a prototype of a Rust interpreter.

The closest is probably rust-analyzer (the official language server), that maintains internal state and reacts to changes you make, but it doesn't create an executable artifact.

The other is probably the Cranelift Backend (https://github.com/rust-lang/rustc_codegen_cranelift), which can produce debug builds quickly.


I meant no reason from a technical point of view. People might say most of the compilation time is spent in the type/borrow checker, but that's orthogonal. You can JIT potentially incorrect code and postpone static checks for a later time (or run them in parallel).


The cranelift backend itself has a JIT mode.


Honestly it would probably be even faster than unoptimized aot compolation


Some developers need/are used to a fast edit-compile-run loop. The JIT doesn't even need to be optimized, just good enough to improve the developer experience.


What were you waiting on? You shouldn't have run cargo build every change. And cargo check shouldn't take that long.


This is a sort of odd phenomenon, but I've noticed that the Rust software I'm developing professionally is never actually getting run before it's pushed to production. We have some unit tests and run those, and if that's fine then into prod it goes. It's honestly a bit insane when I think about it, but it works...


cargo check will take long once you use macros. And now the advice changes to "well you shouldnt use that many macros", and a new criticism will be made, followed by "well you shouldnt....." and a new...

I dont think this wont even work for most kind of programming. I always do an edit-compile-run cycle when im programming, or I break everything to .so and dynamically reload as much as possible. Very easy with C++ and C.

I am waiting on zig and its in place binary patching. But just saying that you should cargo check instead of running and seeing with your eyes if your change made sense or not or is affecting perf or not is....ridiculous.

I think this kind of development flow works better when you are writing already solved solutions or rewriting code. How on earth are you gonna cargo check a perf issue, or a game or memory leaks???


The fact that i got downvoted says it all, people are in delusional mode

Zig devs are tackling the issue early, Rust devs are living with it, it's just sad


adding to this, People that say cargo check is the answer dont even understand the problem at hand.

Just because the language is compiled does not mean it needs to take 30 business days to compile something.

You can have fast compile times and good performance too. SBCL the common lisp implementation is extremely famous in these circles for its performance. IT IS A BATCH COMPILED LANGUAGE WITH A REPL!!

You cannot use cargo check for perf issues, for memory leaks, for trying to solve a problem that does not have a solution...etc etc.

Even then cargo check will make you bleed if you use macros.


I'm hoping this rust fad goes away soon


Be the change you want to see.

I refuse to use rust for a multitude of reasons.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

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

Search: