Earlier quoted context omitted.
Then you are not the target audience of a low-level language that supposed to run without a runtime, but still safely. Don’t try to change the tool, when you could just choose a more fitting one.
Rust has an unsafe subset for that 0.001% of tne time you need it.
The Rust I wanted had no future
391–400 of 523 posts
Re: The Rust I wanted had no future
#392Very interesting insight from Graydon, in hindsight I too would have loved something more towards ML than C++. I never liked the kitchen sink approach that I see first C++, now Rust moving towards, but I respect what Rust has managed to solidify into. It's a good language. That said, I still hate async with a passion, it makes the language more complex and not very elegant (i.e. function coloring). And now that I kno…
I continue to find the "function coloring" argument misses the point unless you're arguing from a developer experience perspective. Why should two fundamentally different things look and function the same? Want this the ultimate pitfall of early RPC implementations where everything looks synchronous?
In Rust, a lot of the friction is due to how async functions/futures fundamentally differ in model of execution and how that interplays with the rest of the language. Other languages get to hand-wave a lot of these problems away with a GC. (It certainly could be less of a pain nonetheless.)
- Futures don't execute until polled, can partially execute if something isn't ready (and would block), can partially execute and be arbitrary cancelled and dropped. There is no equivalent in sync functions unless you make them co-routines.
- Since you can "pause" futures if something would block, you need a place to store the function's state for when it's resumed. Now you must be consider if the async function's state is `Send` if the future wants to move to a different thread to continue executing -- which is why you see `pin!` used. Sync functions don't care about this since you always run to completion on the same thread, and the stack is ephemeral.
- Likewise, the `Future` returned by the async function is going to need to encapsulate it's state that it saves. In the general case, this is a compiler generated anonymous struct that changes if any state saved across `.await` changes, hence the opaque `impl Future`. This is why you see `BoxedFuture` a lot to abstract this away at the expense of an allocation. Ideally, the new associated types with lifetimes can avoid this with traits.
So if all functions were co-routines (i.e. functions that can be resumed and re-entered) they would all have the same "color". But all you really did was "lift" all sync functions to be "async" functions with no internal await points.
(IMHO, if the C# team back in the day decided to implement full blown co-routines into the language instead of just `async/await` as a compiler trick, I think many other projects would have followed suit with a more general co-routine solution instead of treating `async/await` as this special thing which is just a specific compiler generated implementation of co-routines.)
Re: The Rust I wanted had no future
#393Has Rust gone beyond the point of no return? Have less elegant features possibly been embedded in the language that have put Rust on the track to never become the hypothetically perfect or unblemished language?
Re: The Rust I wanted had no future
#394Earlier quoted context omitted.
> Of course, a few of them of say they understand object lifetimes so well, they they don't need the static checker! There is a difference between understanding lifetimes and being able to keep track of them. I have a lot of objects in my more than 10 million lines of code. Most of them have simple lifetimes that are easy to track, but a few for reasons (which may or may not be valid - often the reasons are it was bu…
Being able to stop constantly keeping things in the back of your head and just trusting the compiler to complain if something is off was the biggest differentiator for me by far. Less footguns = more better
Re: The Rust I wanted had no future
#395I love Rust and built some production code with it in the past. But nowadays I want something more simple so that not-so-senior developers can pick it up quickly, and I want flawless tooling, and willing to sacrifice a bit of performance. So basically I often end up with Go. Go is exceptionally great in tooling, ecosystem, any objective metrics like build times or crosscompilation... but I still don't like the langua…
Nim gets real close. It doesn't have great UI tooling, but its command line tools are quite good.
Re: The Rust I wanted had no future
#396Very interesting insight from Graydon, in hindsight I too would have loved something more towards ML than C++. I never liked the kitchen sink approach that I see first C++, now Rust moving towards, but I respect what Rust has managed to solidify into. It's a good language. That said, I still hate async with a passion, it makes the language more complex and not very elegant (i.e. function coloring). And now that I kno…
> (i.e. function coloring) I really wish people stopped using this concept, especially in the context of Rust because the `async fn`/“regular function” split is strictly equivalent to the `try_something()`/`something()` split (the first one being failible and returning a `Result` in case of failure). `Result`s and `Option`s are coloring the stack in exactly the same way a `Future` does (and `async` is pure syntactic…
Tons of stuff in std and many other crates don't use async. A lot of stuff is harder and more code to do async. A lot of it is much harder to read.
That's the difference.
Re: The Rust I wanted had no future
#397Earlier quoted context omitted.
This is just one example, but moves are always bitwise, correct? So if I want an object to track all users of it in C++, I can just make a smart pointer for it whose copy/move/destruction operations notify the object about each event. How would you do that in Rust? (Similarly, what if I want a relative pointer?)
You can track all of this (things like Rc or Arc do) except move. Relative pointers are possible, depending on what you mean. Making this safe (e.g. preventing users of that type from breaking the relative addressing) is done via the Pin type.
Which means you can't track this. Tracking moves is fundamental here.
> Relative pointers are possible, depending on what you mean.
Pretty sure they're not possible in the sense I mean, for the same reason as above - you need custom moves for this. I'm referring to a pointer (not an offset; a pointer) that automatically adjusts itself when copied or moved. So that it always points somewhere N blocks before/after itself.
These are just two examples, to get the point across that Rust actually lacks some capabilities (since somehow that surprises people). You can find more.
Re: The Rust I wanted had no future
#398Earlier quoted context omitted.
Return either value or an EMPTY placeholder. Look Java did it. It returns a nullable value or Optional.
Then I have to check the result anyways. Same thing
It's like Yaml parsers, they had "load_yaml" which is unsafe and "safe_load_yaml" which is the secure option. Imagine no surprise when Rubyists went for shorter safe looking method and got their servers pwned.
Re: The Rust I wanted had no future
#399Very interesting insight from Graydon, in hindsight I too would have loved something more towards ML than C++. I never liked the kitchen sink approach that I see first C++, now Rust moving towards, but I respect what Rust has managed to solidify into. It's a good language. That said, I still hate async with a passion, it makes the language more complex and not very elegant (i.e. function coloring). And now that I kno…
> I too would have loved something more towards ML than C++ I stopped paying attention to the language around 2012-2013 or so when the direction clearly steered towards the latter. You may want to check https://austral-lang.org/ out.
It's even hard real time capable, which makes it potentially viable in scenarios like games where GC traditionally hasn't been.
Re: The Rust I wanted had no future
#400Earlier quoted context omitted.
IDK about donuts. But consider a network request. The vast majority of the time is not spent in the CPU. Right?
Doesn't matter, donut was just an abstraction. s/eat a donut/make a network request/ Is "network request" a synchronous or asynchronous activity? It depends whether your code blocks and wait's until response (or timeout) or continues executing and handling it when it comes. It's property of the "attention" of the caller, not of activity itself.
Something that pegs the CPU to 100% because it's doing intense processing isn't a good candidate for async. Similarly, some code can cause issues when written in a non-streaming fashion. Take the following example (in python):
x = [x for x in range(1_000_000_000)]
y = (x for x in range(1_000_000_000))
If you spawn a bunch of async workers doing the first one concurrently, you'll OOM your system. If you spawn a bunch of async workers doing the second one concurrently, your system will be fine.In other words, "async" is a label on a box of donuts that implies (though doesn't ensure, people can of course still do bad things) that the donut won't explode if you look away from it.