Hacker News new | ask | show | jobs
by nottorp 893 days ago
And these fancy new names aren't there just for hiding the event loop? :)
2 comments

Sort of and sort of not.

The key thing about 2023-era asynchronous versus 1995-era cooperative multitasking is code readability and conciseness.

Under the hood, I'm expressing the same thing, but Windows 3.1 code was not fun to write. Python / JavaScript, once you wrap your head around it, is. The new semantics are very readable, and rapidly improving too. The old ones were impossible to make readable.

You could argue that it's just syntactic sugar, but it's bloody important syntactic sugar.

I never left 1991 and I haven't seen anything that has made me consider leaving ConcurrentML except for the actor model, but that is so old the documentation is written on parchment.
> You could argue that it's just syntactic sugar, but it's bloody important syntactic sugar.

Yes, of course you could, since everything beyond, uh, paper tape, next-state table, and current pen-position (or whatever other pieces there are in a theoretical Turing machine) is basically syntactic sugar. Or, IOW, all programming languages higher than assembly are nothing but syntactic sugar. I like syntactic sugar.

(But OTOH, I'm a diabetic. Gotta watch out for that sugar.)

does this mean that lisp programmers are syntactic diabetics

i hear they're concerned about cancer of the semicolon

Exactly. The way I think about it, the "async" keyword transforms function code so that local variables are no longer bound to the stack, making it possible to pause function execution (using "await") and resume it at an arbitrary time. Performing that transformation manually is a fair amount of work and it's prone to errors, but that's what we did when we wrote cooperatively multitasked code.
> when we wrote cooperatively multitasked code

That's my point, we still do that. And based on your phrasing we're forgetting it :)

Sure, that's a good way to look at it. Another way to look at it: because the process of transforming code for cooperative multitasking is now much cleaner and simpler, it's fine to use new words to describe what to do and how to do it.
cooperative multitasking, as i use the term, keeps you from having to transform your code. it maintains a separate stack per task, just like preemptive multitasking. so async/await isn't cooperative multitasking, though it can achieve similar goals

possibly you are using the terms in subtly different ways so it appears that we disagree when we do not

Cooperative multitasking is "The illusion of simultaneously executing code paths by having said code paths pass control to each other fast enough."

If the OS forcefully switches control it's preemptive.

Coroutines are better than both. Particularly in reasoning about code.
which kind of coroutines do you mean and how are they better
if the implied contrast is with cooperative multitasking, it's exactly the opposite: they're there to expose the event loop in a way you can't ignore. if the implied contrast is with setTimeout(() => { ... }, 0) then yes, pretty much, although the difference is fairly small—implicit variable capture by the closure does most of the same hiding that await does
Not asking about old JavaScript vs new JavaScript. Asking about explicit event loop vs hidden event loop with fancy names like timeout, async, await...
do you mean the kind of explicit loop where you write

    for (;;) {
        int r = GetMessage(&msg, NULL, 0, 0);
        if (!r) break;
        if (r == -1) croak();
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
or, in yeso,

      for (;;) {
        yw_wait(w, 0);
        for (yw_event *ev; (ev = yw_get_event(w));) handle_event(ev);
        redraw(w);
      }
async/await doesn't always hide the event loop in that sense; python asyncio, for example, has a lot of ways to invoke the event loop or parts of it explicitly, which is often necessary for integration with software not written with asyncio in mind. i used to maintain an asyncio cubesat csp protocol stack where we had to do this

to some extent, though, this vitiates the concurrency guarantees you can otherwise get out of async/await. software maintainability comes from knowing that certain things are impossible, and pure async/await can make concurrency guarantees which disappear when a non-async function can invoke the event loop in this way. so i would argue that it goes further than just hiding the event loop. it's like saying that garbage collection is about hiding memory addresses: sort of true, but false in an important sense

What worries me is we may have a whole generation who doesn't know about the code you posted above and thinks it's magic or worse, real multiprocessing.
okay but is that what you meant by 'hiding the event loop' or did you mean something different