Why Rust?
rerun.io
rerun.io
> I can write web apps in another language than JavaScript
> I can write web apps that are fast
Yeah, this is what's worrying me. If you look at rerun.io website, you will notice that it's built with Next.js, i.e. is using a React framework to build pages that have no interactivity whatsoever. Next.js is used for the blog, despite it being just a collection of simple static html pages. Meanwhile, the user has to download around 200kB of javascript for no reason whatsoever; and the only reward that they get for their trouble is an avalanche of javascript errors in the browser console [0].
Is the Rust/wasm future going to look like that?
And the fast argument is missleading at best, every modern language are "fast" enough, if Amazon and Google runs Java that mean it's fast enough for 99% of workload.
And then ironically they then use a complex and runtime-heavy Java-based CI/CD to manage the compilation of their Go codebase.
Go is great though, best bit is how its so useable for web-stuff out of the box. Unlike Rust where you have to spend half your life either re-inventing the wheel or choosing which of hundreds of crates you want to use to do stuff that should be part of stdlib.
Go was created to overcome complexity issues and compile times of C++ (not Java):
https://commandcenter.blogspot.com/2012/06/less-is-exponenti...
If Java could have filled this role in both compile time and memory efficiency, Go in all likelihood would never have been created.
But yes, Go beats Java in compile-time speed as well.
I disagree.
As I see it, JS was invented as a browser utility, as the name implies "script", i.e same as shell script languages such as BASH, for doing small amounts of interactive stuff.
What JS has morphed into is a Jeckyll & Hyde monstrosity. Frontend devs now routinely dump 200kb+ of junk down the pipe at people's browsers because its somehow "better" to dump the processing/rendering on the user's desktop instead of server side.
And then there's the monstrosity of server-side JS. I think few people can argue that JS was ever supposed to be server-side. Things like Node are basically square-pegging JS into that round hole.
The browser is simply the single best application distribution method humanity has ever created. Full stop.
There are literally no other tools that give anywhere close to the same benefits.
So 200kb of scripts might seem "HUGE!" to someone who's thinking about the web as a tool for distributing static information (blog distribution). But in the context of applications 200kb is ridiculously small.
When was the last time you installed an application on Windows/Mac/Android/iOS that was under a single MB?
Yet you install (& run) applications ALL DAMN DAY on the web, without a thought or care.
Things that used to come with 100MB+ installers? Those are web apps now. They serve you 200kb and load in less than a few seconds.
Ex: Outlook used to be a mail client you installed. The installer was several hundred MBs, and it took 10+ minutes to run. Now you point your browser at outlook.com and you get a nearly identical experience.
That spreadsheet app? Just a sheets.google.com away. Loads in seconds - using JS with a tiny payload.
Music player? It's a website now. JS.
See my point?
So is JS a monstrosity? For blogs, sure. For apps? Hell no. It's fucking amazing.
That web application delivery is "fucking amazing" doesn't mean javascript is. Javascript very much is not.
What javascript is, is the only complete option until wasm is way more fleshed out than it currently is.
> Things that used to come with 100MB+ installers? Those are web apps now. They serve you 200kb
With an entire browser and server farm to do that.
> and load in less than a few seconds.
Instead of instantaneously.
> That spreadsheet app? Just a sheets.google.com away. Loads in seconds - using JS with a tiny payload.
10% the functionality, 20% the performance, at twice the heft. Amazing.
> Music player? It's a website now. JS.
Your music library? Doesn't exist now.
No.
Because your point only works if you make (at least) two prior assumptions which are not always true.
Number one you assume everyone has high-speed broadband and "unlimited" 5G on mobile. This might well be the case in many parts of the Western world. But I can point you to a number of rural areas in the Western world and beyond that, in Africa and Asia where this assumption falls flat.
Number two, given most developers use JS to outsource the processing duties, you assume everyone has a half-decent computer. Many people use cheap laptops with lousy Celeron processors and a minuscule amount of RAM, likely also with an ancient browser that has not been updated for ages. Their experience of a browser-app will likely be very different to the cool-kid developer sitting on his bean-bag in a fancy office coding on a spec'd out beast of a machine.
In an ideal scenario of application design, these two assumptions apply as well. So I don't think there is any merit in mentioning them as they're not counter points in any way.
Javascript is not the sole domain of small executables, its not even its primary feature - hell, one of your own examples isn't even very good. Outlook loads nearly 30MB of javascript immediately when you load your inbox, and they update it nearly every other day so you end up downloading hundreds of megabytes just to read your email every single week instead of just once.
But in the context of applications, JavaScript is slow as dog shit.
It takes "seconds" to open my spreadsheet? That is an absolutely deplorable regression.
Personally, I'm fine with 200KB initial downloads, sure that's great and I don't mind repeating them. (But, also don't care about 50MB or even 500MB downloads that I only do once.)
But for the browser to really become the "single best application distribution method humanity has ever created" it needs to be capable of delivering software that executes efficiently or else it is regresssion to barbarism by a thousand cuts. Not just the putrid UX, but we now understand that slow, inefficient code also cooks the planet and destroys various life forms.
I work at a company that uses Google Sheets. So yeah, it does often take seconds to open a document. And I've spent way more time waiting for those sheets to load over the past 5 years than I have waiting for software installers.
And many web apps bog down and lag behind even just typing, because they are doing some (trivial) computation on every keystroke. It doesn't have to be that way, but it often is... because JavaScript.
I'm also bullish on the browser's future as an app-delivery channel — but that is only because I think doing it without JavaScript will become easy, and thus common.
JavaScript is relevant because of the browser, not the other way around.
WebAssembly executes efficiently, it keeps its overhead within a small multiple of natively compiled binaries which is totally par for the course for any JIT-compiled intermediate code. You can write slow and inefficient code in any language, but Rust makes it a bit easier to do things the efficient way.
We are already seeing real world web apps using WASM. (What I have seen is indeed mostly Rust, but in theory there are lots of other languages that can already, or will be able to, play in that same sandbox.)
The other fun thing about WASM is that there are already a bunch of ways to run it on the server (including "at the edge"). That makes it really easy to chop apps up into pieces that run in the browser, or run elsewhere.
Lol. That's not why JS was invented, at all.
JS was invented to provide basic interactivity to static html pages. By accidents of history it snowballed in the current monstrosity.
There are big pushes behind wasm and Rust is leading the way here in a big way. I think you underestimate people and their will not to run javascript. Rust and WASM in particular will make it so that you can bring whatever language you want to the front end.
I believe that while it's very impractical now, wasm will slowly take over and in the future basically no one will use javascript except for basic things and most sites will use wasm for front end logic.
Why? Because it just makes sense for many reasons. You can use whatever language you want both on the server side and in the browser, you can achieve near native speeds and we're already sending big minified javascript blobs anyway so we may as well just send a binary instead. yes it's very hard to make a SPA with Rust today but it is possible and the tooling will become better over time and especially with other languages joining in.
To me it's clear that using javascript on the front end will become slowly irrelevant as more and more devs ship a binary blob. Right now, we need javascript as a glue but I think that will change as well with time.
Honestly, with my previous experience as a frontend web, compile time for frontend is starting to become as bad as a standard compiled language. When you start to have a whole framework, many (many!) dependencies (you know, the kind that make just deleting the node_modules directory slow) and webpack with some plugins for CSS, es-lint and all that, the tooling just can't keep up. It doesn't help that much of the tooling is also done in JS which is fast but not that fast.
If you don't need vite's extensibility, you can go with 'pure' esbuild and slim down transpilation + minification + bundling to only a few seconds.
You have never actually looked at the history of javascript have you? Or at the current "best practices"?
I've definitely seen JS builds be slower than medium to large size Rust builds on the same machine, especially since JS builds often involve large steps that are not parallelized. Rust parallelizes builds pretty well until the very last optimization pass and linker stage.
Go builds are impressively fast, so if that's a big pain point for you I'd look at Go frontend stuff.
> And the fast argument is missleading at best, every modern language are "fast" enough, if Amazon and Google runs Java that mean it's fast enough for 99% of workload.
IMO, it really depends on the workload.
For the stuff that JS is being used for today, you're probably right.
But say someone wanted to implement a CAD program in the browser. I'd say, JS is probably inadequate for that[1]. In that case, performance matters more than for a chat app.
If you look at web development as a spectrum from webpage+ to high performance application, Javascript is a good fit for a large section of that spectrum. But probably not all of it.
---
1. I suppose it depends on the complexity of what you want to display, but "regular" local applications struggle to display extremely complex models today. I'd imagine putting the software in the browser would only introduce additional performance problems.
As someone doing both, my frontend JS/react pipeline has noticeably longer compile times (both to build locally, and for users rendering client-side) than my server-side one.
> There is a reason why JS was invented.
JS isn't here because it's "fast". JS is here because it shipped in browsers, and browsers were popular. JS got fast, after lots of people put a ton of effort into their JS implementations for almost two decades straight to make it so.
(See https://blog.mozilla.org/javascript/2012/12/04/arewefastyet-... from ten years ago as just one of many, many examples)
JavaScript really is a Scheme in disguise with a little bit of Smalltalk. Which really is good. If you don't like junk coming from {}+[] - don't use it, but I consider the lack of errors thrown to be a correct behaviour. Use TS or any other linter to control stuff.
As we can see, Clojure wasn't accepted widely despite the fact it also has first class functions and closures. In my opinion the answer is simple: people want to have syntax for stuff which we agreed is good. Using macros and ((())) is not what people want to do long term.
We are building the frontend of our _application_ in Rust and rendering it to a canvas using egui.rs. For the web site we are using more "traditional" tech, as you've noticed.
I am not a big fan of the complexity of modern web sites (including our own), which is exactly why I created egui. However, it is targeted at web apps, not web sites.
Putting the UI in a canvas elements have some distinct drawbacks (https://github.com/emilk/egui/tree/master/crates/eframe#prob...) but for us it is definitely worth it. Having one unified codebase for our web app and native app, and having it all in Rust, is just amazing.
We're currently working on a 3D renderer based on wgpu (https://github.com/gfx-rs/wgpu) that we will likewise use for both web and desktop.
There is ongoing work to integrate AccessKit (https://github.com/AccessKit/accesskit) which will improve things significantly.
It's currently Windows-only, and I'm working on the big missing feature, which is text editing support.
It is difficult to believe this will be the future of the web.
I don’t think websites should take this approach. Seems like a bad idea
Dear god. And then you can't even visually tell if you are at the main, "Team" or "Blog" page from the menu bar.
This says one thing very clearly: "This website was not made with love." -which says NOTHING about the product they are offering.
So it containing Javascript to fetch the content isn't all that far fetched.
C++ promised to be a language that was both high performance and very expressive but I always found it very difficult to work at a high level of abstraction in C++. The sharp details always stab through.
Rust code, on the other hand, often doesn't look much more elaborate than code I write in much higher level languages but it's far, far faster and I feel more confident in its correctness.
Too bad most of the Rust jobs right now seem to be in crypto.
What is the problem with that?
Matthew Green from John Hopkins University [0]
Zhenfei Zhang of Ethereum, Mina, Algorand blockchains who co-created the NIST post-quantum cryptography standard for digital signatures called Falcon [1]
Nadim Kobeissi creator of cryptocat now created Capsule Social [2]
Silvio Micali, Turing Award Winner for his work on Zero-Knowledge Proofs [3]
So, I'm afraid that there are some credible people like those above who have a significant and documented background in cryptography who are also working in the cryptocurrency industry.
I don't think most of these people are into cryptocurrencies specifically.
They are? Especially the creator of Algorand (a cryptocurrency) Silvio Micali. In his CV [0]
> "Scientific Interests, Cryptocurrencies, Blockchains"
At the bottom of his CV:
> "Technology Transfer: Algorand, Founder and Inventor of the Core Technology"
If that is not 'into' cryptocurrencies, then I don't know what is.
But anyway, the amount of value you can provide there is severely limited, as you can only at most undo the value your government is destroying. You can't ever get in a better situation than what you would get with a competent liberal-ish government and no cryptomoney.
That means some business can exist there, and a small amount of it can even be morally acceptable. But it is completely different from the internet boom.
And what if you have only an incompetent authoritarian government? How would you help fight citizens of those governments? Crypto is a great tool there. Just because there are insufferable crypto-bros peddling shitcoins to make a quick buck doesn't mean entire Crypto field is useless. That'd be like blacklisting the entire data mining field because surveillance tech and adtech exist.
Then cryptomoney can give you a limited, non-zero amount of value. Still less than fixing the government, but it is easier to deploy.
Even then, comparing it with the internet boom is bullshit.
Glad we agree on this. Everything else (eg. comparison with internet boom) is a matter of degree and only time will tell.
(in case it isn't obvious, yes, I fully agree that evading government control/taxation is a hugely lucrative market).
Why do you think governments are always right? Haven't you learned any history?
I'm sure this is the 990th time that I have heard this. The fact is, it isn't going away and it seems even more crypto companies have taken interest in using Rust and that is good.
Even some (crypto) companies are sponsoring the Rust Foundation as silver members. Nothing wrong with that. [0]
(1) Not speculation, gambling, or some variation thereof.
(2) Useful for something other than crypto itself.
(3) Actually works and can be used today.
(4) Continues to make sense even in a crypto bear market. (In other words: I will still buy milk even if the US dollar is falling because the point is the milk not the dollar. What in crypto is like that?)
I prepared that post since the question you posed comes up every week here, if not more frequently.
This was all technically possible in 2009. What I was getting at was… what’s new? Billions and billions have been poured into all kinds of app development and R&D in this space and all we have is still what we had when Bitcoin launched.
What are all these people in crypto building? Where is it? Where can I use it?
Imagine if 25 years after the dot com era after hundreds of billions had been spent we still just had e-mail, static html4, and text chat protocols over dialup modem.
Increased social and political acceptance of Bitcoin as virtual money? That is a big deal.
> ...all we have is still what we had when Bitcoin launched.
False. In 2009, a very very small minority took it seriously. Now you have Blackrocks of the world getting in that business and SEC approving a Bitcoin ETF. So after Billions and billions of investment, now Crypto is a "serious business". Which is exactly why people in Afghanistan and Venezuela can rely on Bitcoin. They wouldn't have done so in 2009.
Another use case is digital art. Until NFTs, I am not sure how artists made money with their digital collections. Now, the creators of Bored Apes can fetch ~75 ETH (~100K USD)[1] per Ape, even today after the Crypto market has crashed. That is durable value and Crypto has enabled that avenue for artists. If you think NFTs are scam for laundering black money, burden of proof would be on you to make a case about why that is different from traditional paintings. And if you think traditional art too is nothing more than an avenue for money laundering, then... I'd propose we agree to disagree.
Yet another use case is branding. Just look at the adoption of NFTs[2] among top brands like Nike, D&G, Tiffany, Gucci, NFL, NBA, La Liga or Australian Open. If legit businesses and sports leagues are adopting Crypto for branding purposes, that is a resounding proof about the viability of this particular use case.
[1] https://opensea.io/collection/boredapeyachtclub
[2] https://www.coindesk.com/web3/top-brands-in-web3-nfts-and-th...
Is their work pointless? Sure. But aren't Googlers' jobs not pointless too? That's the sad state of the 21th century: most people have a bullshit job but they need it to pay their mortgage.
[0] https://www.globalwitness.org/en/campaigns/digital-threats/r...
This is such a bogus argument. I am working in Crypto and have no trouble getting offers from non crypto companies. My resume also carries other evils such as the surveillance overlord and the evil empire, among others. I always found it easy to waltz into a new job with those names.
I have also hired dozens of people coming from companies which were pinatas of du jour. Neither I nor any of the other people involved (sourcers, recruiters, execs, HR) gave even a minimal amount of shit regarding "resume stench". If a candidate passed our hiring bar, we hired them.
So stop spreading this FUD.
Yes, yes I do. I've had a candidate with 2 crypto rug pull startups under his belt, otherwise brilliant and passionate about tech. He went back in for a hat trick. I do not think he displayed proper judgement, do you?
Do you also think that someone who worked on two Google chat apps (which are obviously discontinued) and now working on their third one is showing a lack of judgement?
Not if they recognize the mistake and learn from it.
> Do you also think that someone who worked on two Google chat apps (which are obviously discontinued) and now working on their third one is showing a lack of judgement?
No, it's not fraud and the paycheck checks out. On the other hand, can you imagine? Do you know someone like that?
what if they don't think it was any mistake and was just an honest job?
> can you imagine? Do you know someone like that?
Yes, personally know someone at Google in that space who worked on multiple chat apps and nicely climbed the career ladder.
I wonder why, doing Windows programming with OWL in 1993 was quite delightful, or Mac with AppToolbox/PowerPlant,...
Yes there is always C stuff coming throught the cracks, but I see similar aproaches with Rust code making use of unsafe when there are safe alternatives.
For me, it's because memories are not trustworthy (rose-colored glasses). Also, I had less experience back then. And we as an industry didn't know any better.
I got started in programming in Borland Pascal and Borland C++. Because of nostalgy, I've tried using them for fun again ten years ago and boy is there a reason I stopped using them in the first place. Sheesh.
Example OWL snippets:
for (int index = 0; index < count-1; index++) {
int len = GetStringLen(index);
TAPointer<tchar> buf(new tchar[len+1]);
GetString((tchar*)buf, index);
*outStream << (tchar*)buf << _T('\n');
//delete buf;
}
...
TClipboard cb(*this, false);
if (cb.EmptyClipboard()) {
int len = GetStringLen(index);
HANDLE cbhdl = ::GlobalAlloc(GHND,len+1);
LPTSTR buf = (LPTSTR)::GlobalLock(cbhdl);
GetString(buf, index);
::GlobalUnlock(cbhdl);
...
class tGastValid : public TEdit {
public:
tGastValid(TWindow *Win, short ID) : TEdit(Win, ID) {}
void EvKillFocus(HWND);
DECLARE_RESPONSE_TABLE(tGastValid);
};
DEFINE_RESPONSE_TABLE1(tGastValid, TEdit)
EV_WM_KILLFOCUS,
END_RESPONSE_TABLE;
void tGastValid::EvKillFocus(HWND hWnd) {
GetParentO()->SendMessage(WM_COMMAND, DB_BTGAST, 0);
TEdit::EvKillFocus(hWnd);
}
^-- I liked THAT? What was wrong with me ;)That said, Borland had really good class libraries. If I had those libraries in a modern language, hey that wouldn't be so bad. But these languages? No, thank you.
By the way, you should have a dive into how the "modern" development experience with Rust/WinRT compares with C++ Builder in 2022.
Really? I review and read a bunch of Rust code on a weekly basis from projects I might use in various contexts. I hardly ever see unsafe used, except in contexts where it is necessary like FFI.
I am pretty sure that your comment is provably false, if someone wanted to run a report on crates.io. Oh, looks like someone did, and it trends to 0: https://www.reddit.com/r/rust/comments/g0wu9b/percentage_of_...
From your link: To get this plot I ordered all crates by unsafe code % and then plotted it, so each point on the graph is unsafe code % for a single crate.
The link is still some evidence in support of your position, given that it drops off close to the left edge, i.e., a small number of crates have a large amount of unsafe code. But it isn't nearly the smackdown of GP's position you must think it to be for you to be so aggressive toward them.
I find the statements around unsafe in Rust to generally be incorrect though, from what I can tell, it’s only ever used in quite narrow cases and not generally across the vast majority of Rust software.
Not having looked at that API specifically, it might be that they think there are perhaps different approaches to implementing the safe interfaces, and those may be best left to specific implementations for UI abstraction frameworks, like Druid.
Just speculating.
I've been coding C/C++ since 1995. I'll take Rust any day, thanks.
Don't forget that to contribute to Rust backends on their present forms, some C++ is required.
I never used the C++ version OWL (though i do have Borland C++ 5 around here, perhaps i'll try it for fun at some point), but the Turbo Pascal version of OWL (which i also really used but had a brush with - and some docs) wasn't really that great - more of a helper library for the underlying Windows API, needing to know the underlying API, in practice not very different than MFC (also more of a helper library to make using Win16/Win32 easier than something to let you ignore it).
VCL was by long long far the best API/Framework (and in some ways it still is, though FCL/LCL is better since it is richer and also crossplatform).
FWIW i did a partial recreation of Turbo Pascal OWL in Free Pascal some years ago[0]. It doesn't have much of a practical use though (unless you want to make some small GUI EXE files in Free Pascal) since i think even Borland abandoned the Pascal version of OWL and i doubt many people used it.
Naturally VCL was even better, Microsoft is still trying to catch up with C++ Builder and failing spectacularly at it. C++/CX could have been it, but then the ATL/WRL folks at WinDev had to kill it.
That's the opposite of my experience. The ability to abstract is exactly what I miss since working with C#, with much useful stuff removed to please incompetent developers and their managers.
It is not really surprising that the crypto bros jumped onto the bandwagon, the tech got hyped just around the same time. Just, one of them correctly. :)
It's just a shame that other companies don't seem to follow suit. Except some, who always ask for "Senior Rust Developer" which I'd guess is still a limited supply market. :D
I've seen a role advertised for 750k/month. It makes sens: those who move fastest get to milk the crypto bubble and make out like bandits. Oh wait, exactly like bandits.
We are hiring for Rust engineers. Not crypto. :)
I'm curious to see an example. Could you show something written in Rust, or another "much higher level language" that you think would be messier or more difficult to write in C++ ?
event.SetKeyPress(ch);
event.SetMouseButtonPress(pos, but); etc
...
switch (event.type) {
case EvKeyPress: ch = event.GetKeyPress();
switch (event->type) {
case EvKeyPressEvent:
{
auto kpe - dynamic_cast<KeyPressEvent*>(event)
...
}
break;
}ADTs + pattern matching are the killer feature set that makes the more popular functional languages so damn pleasant to use, and they're starting to spread to more and more languages. I suspect that, 50 years from now, we'll look back and see them as the key paradigm shift of this era.
EDIT: ah, it's algebraic data types, my bad, apologies.
You mean the key paradigm shift of the 1970s when they were invented. Only took 50 years for it to go semi-mainstream.
OOP was invented in the 60s/70s, but the paradigm shift came in the 80s/90s.
Turns out that having a much better tagged union opens up so many possibilities. Software deals with states and what's better to represent states than an ADT? Last time I was fixing an issue where a mouse position is initialized to (0.0f,0.0f) and causes it to trigger a mouse event on startup. The fix was to simply turn it into an Option<(f64,f64)> which is so much better than initializing them as (-1.0f,-1.0f) because it forces you to check all the places where you do arithmetic operations on them.
Blub. It's one of those conceptual steps which seems to have no benefit until it actually clicks and you realise how much it opens or does. Being a tremendously good educator is necessary to make people take that step without experience.
Is an Algebraic Data Type (ADT) in rust an enum or tuple? I make heavy use of enums (along with structs) as my program foundations. Am I using ADTs?
The third type the query shows are unions, which I'm not familiar with.
This is a good explanation: https://jrsinclair.com/articles/2019/algebraic-data-types-wh...
But they’re additionally great because the compiler does exhaustive pattern matching.
It's the combination of both.
Tuples are Product Types. If you treat types as sets of values, then the type (A,B) is the cartesian product of types A and B. For all practical purposes, structs are just syntactic sugar for tuples. Enums are Sum Types. The values of Result<T, E> are fundamentally just all the values of T plus the values of E (with a tag to tell them apart). Put the two things together, and enum Coordinates{TwoD(f32, f32), ThreeD(f32, f32, f32)} is a set of values with cardinality #f32^2 + #f32^3. You can build types corresponding to arbitrary polynomials, hence the name.
"Union type" usually just means the same as "sum type", though it can also be used to mean C-style unions specifically.
(There's also functions as exponential types, with A -> B having cardinality #B^#A, but you're neck deep in type wankery when you start talking about those :o)
Almost every language supports product types in some way, either implicitly or explicitly, and nobody really bothers talking about those in isolation. It's when you add sum types to the mix that people start talking about ADTs, and it's when you add pattern matching that the whole thing comes into its own and you can just express functions as "things with this shape become things with that shape".
𝐴 + 𝐴 ≠ 𝐴
𝐴 ∪ 𝐴 = 𝐴
Note that the particular case of left-pad cannot happen with crates.io/cargo, because once published, you cannot unpublish a crate. You can 'yank' it, in which case it will not be resolved by Cargo.toml, but if you put it in Cargo.lock directly (IIUC) it will still work. So we can't have someone pulling a crate and crashing half the ecosystem.
We can however still have lots of other problems that plague all package management systems. Check out `cargo-crev`!!!! It's an awesome idea I'm always plugging to solve the lack of trust in an open library repository. It requires people to participate though.
Cargo letting libraries easily have their own dependencies means that many Rust libraries are very rich and fully featured. This has plenty of advantages, but the big dependency tree can be a problem in some circumstances. Crate features can sometimes help but usually not much in my experience.
I’ve seen libraries appearing in Rust which are specifically very simple and minimise dependencies (ureq is an example I like). This gives the developer the choice whether they want libraries which just do a small basic job or whether they are okay with including lots of dependencies in exchange for rich functionality. There’s a risk of segmenting the ecosystem (see also async/tokio) but it seems to be working pretty well to me.
In languages where adding dependencies is more difficult, I think things tend to be simpler and thus, more verifiable. But it's also simply harder. I don't know which solution I like better.
[1] ~75 lines of library authorship copyrights https://github.com/ValveSoftware/Proton/blob/proton_7.0/dist...
In terms of checking over the code, cargo dependencies should result in less duplication and so fewer lines of code for the same level of functionality, and having it split into crates doesn’t obviously make it harder to review and Cargo.lock means the dependencies won’t change unexpectedly.
I do agree that there is a question about whether easy access to pulling in dependencies means libraries are more inclined to bloat and unnecessary complexity. But not having cargo dependencies at all would seem like a very big hammer to solve that problem. I’d much prefer to grow an ecosystem of minimal/simple libraries which don’t try to do everything and which limit their dependencies.
cargo lichking is an example, and I think cargo deny has similar functionality?
(I did use some tool like you mention, but my recollection is they were pretty crummy. IIRC they just did a dumb full dependency graph, so included stuff required only for platforms that I wasn't deploying for; also I think the output format was ludicrously verbose so I had to manually trim it down. This was a couple years ago, perhaps the tools have improved since then.)
Good point about the yanking. But yes, there are multiple other problems such as typosquatting and adding malicious code to a patch release. `cargo-crev` and `cargo-vet` are both interesting tools that I'm keeping my eye on.
I feel this! I absolutely love rust's fancy enums - i.e. not just a set of constants, but where each variant can be a full fledged type of its own, and how you have to handle every case whenever you're matching on it. It dovetails absolutely wonderfully with non-nullability and errors as values. This is probably the main nice-to-have in a language for me. Unfortunately, I don't really work in a low-level domain so I'm not sure the extra complexity of manually managing memory is worth it to me.
Do any other higher-level languages have rust-style enums with exhaustiveness checking? I only know of Haskell and Ocaml. Actually, I suppose TypeScript has something kind of similar.
Erlang has the superpowered version of this - binary pattern matching, that lets you pattern match on a bitstream directly.
Erlang has a super-powered version of the pattern matching bit, but not of what GP actually likes about it:
> you have to handle every case whenever you're matching on it
because Erlang is dynamically typed. So partial patterns are acceptable, and not entirely uncommon.
Also faillible patterns outside of conditional contexts. It acts as an assertion which is nice, but the assertion is implicit which is less nice.
Then they became part of the C language when they evolved into enums but still remained compatible with int's (you could cast an enum to an int).
In that mindset it never occurred to anyone that an enum could have an "internal" value too.
One thing I can't seem to find a quick answer to from the Rust crowed is how does Rust handle dynamic lifetimes? It seems like it does not; it simply prevents you from referring to objects that have a dynamic lifetime not known at compile time.
You either have to use 'unsafe' or use the 'handles' pattern where you have what amounts to a custom allocator but the compiler does not know that it's an allocator so it can't prevent 'use after free' bugs.
I suppose you can also use Rc, but isn't that essentially a garbage collection scheme, with similar performance characteristics? (AFAICT a reference counting scheme must be able to nullify all references to an object when it's deallocated, so deallocations can become arbitrarily expensive).
Am I missing something?
What do you mean ?
If you refer to heap allocations, then you can use Box, Arc, Rc. They are not a "garbage collector" nor do they incur performance hits other than a regular heap allocation.
If your issue is "atomics are slowing down my app", then I assume you already milked the code to the latest micro second of performances everywhere else. This is likely not the case here and not a general advice I would give to anyone.
Remember, some dev in python where concurrency is inexistent, start-up time is horrendous and performances are abysmal compared to rust. (this is exaggerated: of course you can run stuff in parallel in python)
Once you have an Arc<T> you can `as_ref()` to get a &T. So maybe you need an Arc to share something with another thread, so you clone it once. Once you're in that thread though you can go back to just using `&` and never touch the atomic again.
The cost is also more predictable/amortised than classic garbage collection.
The point about predictability is totally valid though (and combined with simplicity is the reason many languages still pick ref counting).
Furthermore Rust can also safely borrow from a refcounted pointer without the need for refcount traffic, which can be quite the performance gain for atomic refcounts (it's nigh irrelevant for non-thread-safe refcounts as those just do a local increment/decrement).
And for systems programming, the often overlooked truth is that people care far less about perfect performance than they do about control - ref counting doesn't give up control to a mysterious oracle running in the background which may or may not wreck your performance in hard to predict ways, it just pays a known cost at the time you use it based on how you're using it. (that's not to say performance is irrelevant, but it's not always the top concern, and with control you can always rewrite slow code as needed).
The obvious question is "why can't we have an optional modern garbage collector built into a systems language?", and it's a good question (I remember reading there was one in rust for a while during early development, but it got removed), I think the main reason is that high quality garbage collectors are incredibly complicated, with many trade offs, and a gc that combines well with the rest of a language and various alternative memory tracking solutions is harder than most. The projects that really want one can always implement their own and choose their own tradeoffs, so there's not many use-cases where a generic language-provided one would justify the complexity of implementing it within the language.
It's possible in C#. Some language and runtime features like lambdas insist on using the GC, but with some care they can be avoided. The usability becomes worse without these features, but IMO that's not a dramatic downgrade.
Many pieces of the standard library in modern .NET don't require managed heap. Instead, they operate on stuff like Span<byte> which can be backed by anything: unmanaged heap, native stack, or even the memory mapped to user space by a Linux device driver (I did it with DRM, V4L2 and ALSA devices).
The idea of reference-counted object is that by the time it's deallocated there _are_ no references left to update. Now you might reasonably be asking about the memory left behind by those old references which contain now-invalid pointers. The use-after-free risks of any single given reference to the object is something the Rust compiler can reason about quite easily. Once you drop one of them (and the refcount decrements) you are guaranteed not to be able to get at that pointer again; not until that memory is reinitialised with something else valid.
A weak reference does not prevent the object from being deallocated, but the system guarantees that when the object is deallocated, all weak references to it will be nullified.
This is what makes deallocating objects in a refcounting system potentially arbitrarily expensive.
It does:
- https://doc.rust-lang.org/std/rc/struct.Weak.html
- https://doc.rust-lang.org/std/sync/struct.Weak.html
> A weak reference does not prevent the object from being deallocated, but the system guarantees that when the object is deallocated, all weak references to it will be nullified.
> This is what makes deallocating objects in a refcounting system potentially arbitrarily expensive.
Depends how you implement weakrefs. In Rust, when you upgrade a weakref it checks if there are outstanding strong references, and if there are not the control block is considered invalid and the upgrade fails.
There is no need to touch any of the weakrefs at any point.
And unlike languages like Python, Rust does not have weakref finalizers either.
Deallocation is still arbitrarily expensive in general, as the entire subtree will get deallocated recursively, but that has nothing to do with refcounting.
The way it works is, in order to use it you try to upgrade it to a normal Refcounted pointer. Since it is a weak reference, this upgrade may of course fail and in that case return None (in place of a null pointer). When this upgraded pointer dies (either goes out of scope or is manually downgraded) the refcount will again be updated.
- Use Rc (or Arc if you need to be thread-safe)
- Use a Vec, slotmap, or a similar data-structure and store handles (indexes). This doesn't entirely prevent use-after-free bugs. But it does tend to make them panics rather than silent errors.
- Use unsafe (and ideally create your own higher-level safe abstraction)
In theory, there should also be 4:
- Use a GC library
But I haven't seen a good implementation of this yet.
---
If you're missing something, it's perhaps that most lifetimes aren't dynamic. So you get all the benefits of Rust's ownership in the 80% case. And in the 20% case you don't get any particular benefits, but you still have all the same options available to you as in other languages.
But if you're stuck with legacy code in $WORK you are stuck with raw/smart pointers and these really have lots of issues.
Can you even imagine other options, though? If enough information about the lifetimes isn't known at compile time, how can the compiler prove it safe?
Rust just prevents you from doing this. So you can say it provides safety, but it also restricts you from solving the vast majority of serious problems that we write programs to solve.
This is very different from static vs dynamic typing.
In a statically typed language, the compiler actually _knows_ what you can and can't do with each object.
Where as Rust's life time management just says "Nope, I have no idea whether what you are doing is safe or not so I'm just going to tell you you can't do it".
Since 1.62 there have been a native way of doing it with the `total_cmp` method [0] on floating points which can be used to at least sort it quite easily, but cannot really use it in collections like BTreeMap.
[0]: https://doc.rust-lang.org/std/primitive.f64.html#method.tota...
Given the nature of floats, is this really a problem?
Worst case scenario the floats can be represented differently, if one really needs to use them as keys.
Maybe I can use a combination like c and lua to get the right trade offs between safety and performance in the necessary parts of my program but I'm not that confident that I can reach either safety or acceptable performance doing that.
Maybe, I could use C and some kind of static analyzer to find all of my memory bugs. Again, I'm not confident I would succeed there. I might also need a fuzzer to do it. At this point I'm trading a complicated language for a easy fast language with extra complicated operations that may or may not give me the outcome of memory safety.
So far it doesn't seem to be insurmountable but it's definitely not what I'd call simple.
As far as memory safety do you think it would be a good idea to write something like say a http server or client in Zig?
In a perfect world where developers could tinker with the code until it's perfect we wouldn't need Rust. This is not that world.
Imagine big but perfect Assembly codebase against an okay-ish Rust codebase. Which one would you prefer to maintain?
For me, Rust looks like a temporary step before the next language.
Yes syntax is verbose, but I dare to believe there must be another blocker than just syntax?
I'm still learning both Ada and Rust, so please keep that in mind. Nevertheless, I humbly disagree. The more I learn Ada and other "old" languages the more it looks to me like "modern" ones rediscover things that have been present in other languages for years.
The really significant difference I can see for now is that Ada is not focused so strongly on functional programming paradigm and it has no async/await sugar. Rust borrow checker is a strong success of course and was another significant difference, but latest SPARK got borrow checking capabilities too, AFAIK.
While Ada's open-source community is smaller, I find it as energetic and devoted to improving the ecosystem as Rust's. I have no idea about closed-source community, but in the past 4 years ArianeGroup [1], Airbus [2] and Nvidia [3] talked about choosing Ada for their high-integrity applications.
> And to be fair, it is fine. ADA is very much a "committee" language (its spec are ISO/IEC) instead of a "community" language (all the spec and rfc of Rust are on github and anyone can easily discuss them).
You can discuss Ada/SPARK RFCs on Github too. [4] I think I once saw on Ada forum or chat that someone proposing changes to the language was simply invited to talk to people working on the standard, so it doesn't look like the language is developed in isolation or something.
> This makes it so that ADA doesn't get the attention, and the rapidity of innovation, that a language like Rust does, but ADA is mostly made for program that will need to be maintained in critical operations for decades with the code being maintainable and compilable far into the future.
I think that Ada adopted quiet quickly to changing world with Rust as its inspiration: lower entry barrier toolchain, compelling licensing, library distribution, RFCs, etc. And in terms of language features, in many areas it's not only on par, but ahead of competition. So you're less likely to see lots of changes, but they do happen nevertheless. I'm not saying Ada is perfect, of course. There are parts of it that other languages do better. No shame in that.
IMHO, the reason Ada is unknown to many people is a combination of its past, myths surrounding it, and general trend of people to follow trends. ;) But currently I find Ada/SPARK even more compelling option than Rust, even though I like both.
[1] https://www.facebook.com/ArianeGroup/posts/2872955946126067
[2] https://www.manufacturing.net/aerospace/news/21175187/airbus...
[3] https://blogs.nvidia.com/blog/2019/02/05/adacore-secure-auto...
I've written in Ada95 back in college and it was great but I'm like a duck in water with Rust.
AFAIK, the newest SPARK got borrow checking capability. Also, Ada has excellent design by contract capabilities [1] and constrained subtypes [2].
> Add on things like cargo build manager and crates and it's like a delicious roast dinner smothered in gravy.
Ada has now Alire [3] for that.
> I've written in Ada95 back in college and it was great but I'm like a duck in water with Rust.
Ada is nearing the 2022 standard now. It changed a lot since 95.
PS. I have nothing against you liking Rust. Just wanted to clarify few things.
[1] https://learn.adacore.com/courses/intro-to-ada/chapters/cont...
[2] https://learn.adacore.com/courses/intro-to-ada/chapters/stro...
There was a lot of hype about OOP too, but I am not sure it was ever adopted because of it.
That came a lot later in its life, like mid to late 90's.
But was C++ widely adopted at that time? I remember C++ compilers being a huge pain by the middle 90s. I can't imagine everybody using them earlier. (But then, it wouldn't be the first time everybody just decides to do something I can't imagine.)
(Does C++ have its warts? Absolutely. But it's a huge productivity boost over C.)
Rust is just way better thought out on a deeper level than C++ ever was (or is). It has its issues, and while it may suddenly accelerate adoption in the next several years, I don't actually seeing it gaining many inroads. I hope to be wrong! I think, these days, language kinda doesn't matter as much, as all languages are picking up chunks and pieces of all the various paradigms, like a decorator crab, and that tends to work fine for established code bases.
Them's fightin' words. SBCL (Lisp) totally screams with speed as far as I've been able to tell.
Its runtimes are all like 5X C's. Not sure I would say "screams", it looks like it keeps up with Java though.
If you think Rust is bloated, I agree.
1. You used an in-progress compiler to build a project and you're drawing conclusions about the language it compiles?
2. The compiler is huge, why does that imply any "bloat" of the language? Compilers do lots of things that aren't "visible" at the language level - optimizations, producing helpful errors, providing code completion/analysis assistance, etc.
3. What does "bloated" even mean?
4. What makes you think that 20 hours is very slow? Have you tried building Clang and llvm together from source? It can take quite a while, but it also depends heavily on how you build it (which build system, flags, etc), which you've not given any information on.
The issue is that the app itself will not really be needing maximum performance and I much more concerned about the safety aspects Rust brings. But I guess the safety aspects would be the same with me using Python for example.
Why I want to learn Rust is because it could help me in the front end aspect and I think it's a language that has a bright future.
Am I crazy to spend the time to get effecient in Rust and write my app I want to write in Rust instead of Python? Is there any other benefits of using Rust that I don't see as a beginner? I am afraid that I'll just waste a bunch of time just because I want to learn Rust and think it's cool but ultimately it will slow me down to such an extent that my app never sees the light of day or that it increases general development time.
Thanks in advance for all potential responses
I imagine the following would be needed..
1) Spring MVC like library for interfacing with HTTP requests.
2) DB ORM or ORM like. DB libraries for any possible DB.
3) centralized logging. e,g, Logback that forwards all logs to ELK.
4) Dependency injection.
5) Versatile configuration system. Similar to Spring configurations.
6) AWS SDK.
7) Commons like libs like Guice or Apache Commons.
stuff like that.
I don't do any fancy configuration. I use `clap` to take in values and ideally I'll never do any config anywhere else in my program.
The AWS SDK from rusoto works well enough. AWS has a beta SDK out for Rust as well, seems good.
I haven't found any need for libraries like Guice, there's metrics, collections, and everything else I've needed in crates.io.
That's my company. The blog is hosted elsewhere. Our frontend is hosted via a rust service, which talks to other rust services via grpc.
You can choose your own template engine instead of having to use one that's provided (like in ASP.NET MVC). There are a multitude of template engines available in Rust.
Can you explain why DI needs an entire framework/libary?
When I was taught DI in school, I was given the impression that DI was a $1000 term for a $5 concept in that without DI, you write code like this:
class Foo(object):
def __init__(self):
self.bar = GetBar()
whereas with DI, you write this: class Foo(object):
def __init__(self, bar):
self.bar = bar
Obviously, I'm grossly misunderstanding what DI is, because if that's really all it was, you wouldn't need a DI framework. I just haven't had to write code using any sort of DI more complicated than that.Do you know any good references for describing DI frameworks more? Because right now, my cynical take based on your description is that it's a TON of over-engineering and an absurd amount of complexity being added just to avoid a couple extra lines of code.
IDE's like Visual Studio hide this behind tons of settings and dialogs but in the end it's simple if you know the above.
cargo just works, and isn't really complex in design. just less anticated.
> If I'm honest, the main reason is because I love Rust.
That's nice if it works for you, but I'm looking to build and maintain software well and efficiently. I don't want a programming language I can love I want a tool. (BTW, old and tired but true: don't love things that can't love you back.)
I understand Rust is fast, but how does it do with complex abstractions?
There's a `rand` crate[0] which I believe was written by folks in the Rust project, though it's not part of std. You can seed the RNG[1].
[0] https://crates.io/crates/rand, https://github.com/rust-random/rand
[1] https://docs.rs/rand/latest/rand/rngs/struct.StdRng.html#met...
Guilty as charged
The majority of software is slow and not safe to use and the majority of people do it anyway.
is_hiring()?.apply()?.code_rust()?
Error handling is really nice in rust
Edit: Just realized that the first question mark in my original question was a mistake