I Hope Rust Does Not Oxidize Everything
gavinhoward.com
gavinhoward.com
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.
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_.
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.
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.
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.
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.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.
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++).
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 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.
https://blog.cloudflare.com/how-we-built-pingora-the-proxy-t...
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.
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.
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 :)
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.)
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...
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.
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?
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.
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.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.
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.
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.
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.
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 ?
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.
So many different solutions. Most are preferred because of subjective reasons (although sometimes just poor reasoning period), because people think so drastically differently.
That's how you wind up with C++
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 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.
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++.
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.
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.
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.
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 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.
I’m very interested in what you mean here. Isn’t the syntax identical in both cases?
&array[index]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.
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.
These are massive problems
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.
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'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
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
That said, you're right that it could use a row for the lifetime syntax.
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.
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."
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?
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.
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
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.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.
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...
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/
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.
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 ...
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.
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.
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.
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.
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.
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.)
Mine too, but my post implied it, and it was already too ranty.
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.
I have to look up how to write the where part properly every single time.
That's exactly the people you want to hear from if you're trying to improve adoption.
This isn't the problem, the problem is "... and keep the syntax C++-like?".
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)
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.
* 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.
Make that "not far off C++" (C is really beautiful in comparison), and there's your answer.
That and the colon-colons (::), probably. Those can add a lot of noise.
I prefer "quad-dot". Rolls off the tongue better. :)
< 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"Lifetimes are really ugly. You usually don't need to write them explicitly, but that's not a real excuse.
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 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 valueHowever, 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".
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
- It was made to be approachable for C++ experts
- The idea was that language could be effortlessly greppable.
But it is naive to think that not using it is an easier path towards a solution.
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...
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.
- 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.
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.
I think there's something close - https://caramel.run/manual/
This is practically impossible to retrofit on to an existing language, esp. in the presence of loops.
Talk to your friends and family.
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
- 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 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.
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.
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.
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.
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.
[1]: https://git.yzena.com/Yzena/Yc/src/branch/master/src/yao/exa...
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.
* 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
And the rantiness comes as a side effect of that.
Fixed, Thank you!
I still think it's better than C++ but for large projects the compile times and crate splitting, etc. become a real pain.
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.
I tried to work on bug fix for Zed, waiting 30 seconds everytime you change a value was _very_ painful
(Outside of compile times, which are a well known point)
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 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???
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.
Zig devs are tackling the issue early, Rust devs are living with it, it's just sad
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 refuse to use rust for a multitude of reasons.