I think Go got it right by inverting the logic around async/await. In Go you have to explicitly state that a function is to run in the background via "go fn(...)". This makes it much clearer that this code will execute concurrently. In the async/await world you can't tell by looking at a function call if it will block until it's done. Forgot an await? No compile error but your program might behave in weird ways. This…
It wouldn't work. In Go, it doesn't matter how deeply nested a call to a blocking function is, when you do "go f()" the runtime takes care of things. With async however, if "await" is the default, then as soon as an async function calls another async function, it would block, completely defeating the point of async in the first place. I guess you could flip the rules and say that within an async function async is the…
How to think about async/await in Rust
31–40 of 268 posts
Re: How to think about async/await in Rust
#32Not specific to rust, but I think asynchronous programming in general is a hype. It didn't start because it is so awesome, it started because JS can't do parallel any other way. That's the long and short of it. People wanted to use JS in the backend for some reason. The backend requires concurrency. JS cannot do concurrency. Enter the event loop. Then enter some syntactic sugar for the event loop. And since JS is pop…
https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
https://news.ycombinator.com/item?id=36597229 (fresh repost)
Discussed previously:
https://news.ycombinator.com/item?id=8984648 (8ya)
https://news.ycombinator.com/item?id=16732948 (5ya)
https://news.ycombinator.com/item?id=23218782 (3ya)
https://news.ycombinator.com/item?id=28657358 (2ya)
[0]: https://kristoff.it/blog/zig-colorblind-async-await/Re: How to think about async/await in Rust
#33Not specific to rust, but I think asynchronous programming in general is a hype. It didn't start because it is so awesome, it started because JS can't do parallel any other way. That's the long and short of it. People wanted to use JS in the backend for some reason. The backend requires concurrency. JS cannot do concurrency. Enter the event loop. Then enter some syntactic sugar for the event loop. And since JS is pop…
It began in C# in 2012 - 5 years before JavaScript. And C# does threads. And made its way to JavaScript via Typescript (whose creator also created C#).
Re: How to think about async/await in Rust
#34I think Go got it right by inverting the logic around async/await. In Go you have to explicitly state that a function is to run in the background via "go fn(...)". This makes it much clearer that this code will execute concurrently. In the async/await world you can't tell by looking at a function call if it will block until it's done. Forgot an await? No compile error but your program might behave in weird ways. This…
You're talking about particular JS implementation problems, not general async/await problems. > In Go you have to explicitly state that a function is to run in the background via "go fn(...)". In Rust you have to explicitly `spawn` a task to detach it from the current coroutine and make it run in background. Typically this is much more costly than not spawning and executing async function concurrently as part of the…
> foo();
Only if you know that foo is an async function. You can't tell by the function call itelf. > warning: unused implementer of `futures::Future` that must be used
Interesting, I haven't seen this warning in the Rust codebase I worked a little with. I'll have to check the compiler settings. Anyways wouldn't it make sense to actually throw an error instead of just a warning? > Additionally there are certain things you are not allowed to keep across await points, e.g. mutex guards or other stuff that's not safe to switch between threads. E.g. using a thread-local data structure across await points might break, because you could be on a different thread after await. If await was hidden, you'd likely be much more surprised when the compiler would reject some code due to "invisible" await.
Why couldn't the compiler clearly state the reason for the error though?Re: How to think about async/await in Rust
#35Not specific to rust, but I think asynchronous programming in general is a hype. It didn't start because it is so awesome, it started because JS can't do parallel any other way. That's the long and short of it. People wanted to use JS in the backend for some reason. The backend requires concurrency. JS cannot do concurrency. Enter the event loop. Then enter some syntactic sugar for the event loop. And since JS is pop…
Re: How to think about async/await in Rust
#36Not specific to rust, but I think asynchronous programming in general is a hype. It didn't start because it is so awesome, it started because JS can't do parallel any other way. That's the long and short of it. People wanted to use JS in the backend for some reason. The backend requires concurrency. JS cannot do concurrency. Enter the event loop. Then enter some syntactic sugar for the event loop. And since JS is pop…
NodeJS did it right, and it's hard to call a 14-year-old technology a fad.
Re: How to think about async/await in Rust
#37Not specific to rust, but I think asynchronous programming in general is a hype. It didn't start because it is so awesome, it started because JS can't do parallel any other way. That's the long and short of it. People wanted to use JS in the backend for some reason. The backend requires concurrency. JS cannot do concurrency. Enter the event loop. Then enter some syntactic sugar for the event loop. And since JS is pop…
Hmm, wasn't the whole point of doing things in event loop because it way out perform thread-based architecture? Like when Nginx way out performs Apache? On a single core CPU of course.
Edit: It is not that event-loop is better than thread-based, just in a web server scenario it just perform much better.
Re: How to think about async/await in Rust
#38Earlier quoted context omitted.
You're talking about particular JS implementation problems, not general async/await problems. > In Go you have to explicitly state that a function is to run in the background via "go fn(...)". In Rust you have to explicitly `spawn` a task to detach it from the current coroutine and make it run in background. Typically this is much more costly than not spawning and executing async function concurrently as part of the…
> foo(); Only if you know that foo is an async function. You can't tell by the function call itelf. > warning: unused implementer of `futures::Future` that must be used Interesting, I haven't seen this warning in the Rust codebase I worked a little with. I'll have to check the compiler settings. Anyways wouldn't it make sense to actually throw an error instead of just a warning? > Additionally there are certain thing…
That's fair point, but traditionally you don't use blocking functions in async contexts at all. It is fairly easy to lint for by prohibiting some inherently blocking calls eg.g std::io, although they might sneak in through some third-party dependency.
This doesn't have an easy solution because Rust is a general purpose language that allows different styles of concurrency adapted best to the situation, instead of one-size-fits-all like Golang.
Rust has means to annotate functions so maybe there will be some automation to deal with that in the future, similar to how `#[must_use]` works now. E.g. `#[blocking]` or whatever.
> I'll have to check the compiler settings.
This is with default compiler settings.
> Why couldn't the compiler clearly state the reason for the error though?
Stating the reason is probably solvable problem, but there is another problem: what if 5 layers down the call chain something suddenly introduces a potentially blocking (awaiting) operation? This would mean that some code that previously compiled now has to stop compiling even though it hasn't changed and even though none of the signatures it uses changed. I guess it would break things like separate compilation.
And again, it would be less readable than it is now. Now it is fairly simple - you don't have to look down the call chain to know that something can do await.
Re: How to think about async/await in Rust
#39Re: How to think about async/await in Rust
#40Not specific to rust, but I think asynchronous programming in general is a hype. It didn't start because it is so awesome, it started because JS can't do parallel any other way. That's the long and short of it. People wanted to use JS in the backend for some reason. The backend requires concurrency. JS cannot do concurrency. Enter the event loop. Then enter some syntactic sugar for the event loop. And since JS is pop…
I'm curious, what reason?
I grew up on Python and C#, and only know async/await, never done real threading (C# async is threading and coroutines under the hood, Python is just coroutines, single-threaded). I find that way of writing code very elegant, as one can encode points of blocking/switching explicitly. A bit like encoding logic into the type system (cliffle has an article on the type state pattern, a good read!): the underlying async implementation can change without code adjustments.