lobsters score: 1 · tags: rust
You avoid function coloring. It’s a function parameter.
I have a problem with this wording, because function coloring is isomorphic to function parameters. It is fundamentally about how if you need thing X as a parameter at the bottom of the callstack, it will spread upwards. It doesn’t really matter whether the parameter is implicit or not. And it also goes for return types: if you introduce a Result at the bottom of your previously-infallible stack, it will start to spread upwards, unless you bite the bullet and unwrap it. Which will then unwind the stack so philisiphically it still does spread upwards, except implicitly and invisibly.
score 1 · canonical
This is a very insightful observation, thanks. On a related note, effect systems seem to unify all three of these (function coloring, state parameters and error propagation) but I was never able to articulate why should they be related until reading your comment.
unless you bite the bullet and unwrap it
Or for async, block the current thread on the future.
score 1 · canonical
Wow, that’s a great post, I learned a lot about async Rust from it that I had no idea about! Especially from patiently reading all the collapsed sections 😁
Regarding the passing of IO/async/… in Zig - I don’t know much about it, but just from what you wrote, it also sounds interesting to me from a point of view of an explicit “capabilities passing/tracking” system! Or, in other words, “side-effects” stuff, like in Haskell I think maybe? (Also don’t know that one well.)
score 1 · canonical
The crate thing is how you get Tokio defaultism, and a lack of runtime agnosticism
If only there was some kind of way for all libraries to be parameterized over the runtime…
I don’t have it in me to do research on that today, but figuring out which types of programs would benefit from [kernel-managed M:N thread type things] and what the limitations are is an interesting question. In practice, the kernel will never know as much about your code as a language-specific runtime.
With the “kernel vs userspace for $thing” question, it’s faster to “stay where you already are”. Context switches are expensive. And it seems really hard/awkward to schedule from the kernel without yield points being extra context switches. With old-skool poll-based I/O, you could maybe try to attach the next task choice onto the poll syscall itself but that would only improve the situation for the tasks that are directly waken up by external events (like socket readiness). Bouncing from one task to another would still be “extra” poll calls then.
Now that Linux has realized that completion-based I/O scales a lot better, we’re firmly in the “fewer syscalls actually” territory…
score 1 · canonical
If only there was some kind of way for all libraries to be parameterized over the runtime
Fun fact: Graydon Hoare wanted Rust to have ML-like first-class modules!:
Traits. I generally don’t like traits / typeclasses. To my eyes they’re too type-directed, too global, too much like programming and debugging a distributed set of invisible inference rules, and produce too much coupling between libraries in terms of what is or isn’t allowed to maintain coherence. I wanted (and got part way into building) a first class module system in the ML tradition. Many team members objected because these systems are more verbose, often painfully so, and I lost the argument. But I still don’t like the result, and I would probably have backed the experiment out “if I’d been BDFL”.
Makes me curious how such a Rust would have turned out, especially if some of the more modern OCaml module features mentioned in your link were implemented.
score 1 · canonical
these systems are more verbose, often painfully so
Heh, well, it is indeed kinda painful to use them as a general substitute for traits. It really shouldn’t be one or the other, it should be both.
score 1 · canonical
I honestly think there is a big misunderstanding what Zig does. The
ioinstance that is being passed around is the interface. If you actually look how it works under the hood, all implementations reach into a thread-local to get the actual state. Theioinstance is primarily only used to determine which functions to actually run, and once you are in the right function, where to spawn new tasks. For I/O operations, theioparameter is usually ignored. Reach into the thread-local, determine status, do the operation.
score 1 · canonical
trying my best to complain about async Rust, only to end up going “Oh. Yeah. That’s reasonable. That makes sense. I can see why they did it that way.” every step of the way.
I never understood the complaining about async rust. Is it like kubernetes/react where people just kneejerk into it?
score 0 · canonical
The complaint about Tokio having the “hidden runtime argument” passed around is very valid. I think the attempts to “erase” asynchronous runtimes and attempting to make them invisible to the user hurts more than it helps for comprehension.
score 1 · canonical

