This is an excellent article not just because it explains this new concurrency library for Guile, but also because it demonstrates the fundamental concepts which underlie all concurrency. Processes in a Unix kernel, for example, deeply and directly parallel this implementation of fibers on a Guile VM.
I've been playing around with delimited continuations in a toy programming language of mine for a while now and I seriously think that its a paradigm that will eventually take over the scripting language space. First-class control flow is so powerful once you get the hang of it!
The page that you linked to shows off some features that are not really found in any major programming langauge. Time-traveling search is a big one for me.
Many languages have exceptions, but with shift/reset, you can implement your own exception handling behavior trivially, including things like resumable exceptions.
Some languages have async/await, but almost all of those implementations are state-machine based, which means that they don't compose well when used with more complex language features like generics and higher order functions.
But more than that, in continuation-based asynchronous programming, "async" functions are just normal functions that execute in an async prompt. Here's an example of a multi-user asynchronous TCP echo server in my toy language with tagged delimited continuations:
async {
loop {
let conn = accept_connection("localhost", 9999)
async {
loop {
let data = conn.next_data()
conn.send(data)
}
}
}
}
Where all of those asyncrhonous constructs (including `async` itself) are really short wrappers around delimited continuation machinery.
You'll notice that the nested calls to `async` indicate that there are two asyncrhonous contexts
1. Connection acceptance happen on their own "thread" of control
2. Each connection gets their own context in which everything is internally asyncrhonous
time-travelling search can be done with recursion. Otherwise, i agree that they don't compose well with each other in some languages. However, it is harder to implement efficiently as far as i understand; time will tell if they are widely understood to be implemented in future languages.
Another thing that I should mention is that most langauges, features like generators / async / exceptions don't compose well at all. In a language where these features are implemented through continuations, it's really easy to pick how they interact, leading to some really powerful tricks!
Delimited continuations are in the Racket standard library. Racket's thread system isn't built directly on them but is also lightweight. The in-progress work to run Racket in Chez Scheme uses an implementation more like what wingo describes, based on what's called "engines".