V8 adds support for top-level await
251–260 of 310 posts
Re: V8 adds support for top-level await
#252So COMEFROM is now a first-class feature of the most popular programming language in the world. Intercal really was ahead of its time.
Just like Lisp and Algol 68 on other domains, apparently good features tend to take time to become mainstream.
Re: V8 adds support for top-level await
#253All this async code without decent locking primitives is leading to a rabbit hole of race conditions... It doesn't matter that it's all single threaded if all your function calls may or may not block and run a bunch of other code in the meantime, mutating all kinds of state. I feel like JavaScript developers of the 2020's are going to relearn the same things the C programmers of the 1990's learn, just a few levels of…
Javascript devs, for all their flaws, understand async programming far, far better than the average C programmer. Indeed, your assertion that we need "locking primitives" to counteract "race conditions" is evidence of that. Yes, JavaScript can have race conditions, but not multi-threaded race conditions that cause resource contention [0]. So what good would locking primitives be? And as a solution to single-threaded…
You know that Javascript is a C(++) program? That when you use TCP, the protocol is in C? The ethernet driver is written in C? The OS scheduler is written in C? That you're programming in a little sandbox, and all the concurrency around you in managed in C?
There has never been anything synchronous about C.
Re: V8 adds support for top-level await
#254Earlier quoted context omitted.
He got the terms wrong but he’s absolutely right. > There's no way for multiple branches of code to access the same variable at the same time in JS. This is 100% true and it’s the very reason why we do not need locks. There is no thing called a critical section in JavaScript because in JavaScript all of your code runs on a single thread and it’s all equal therefore none of it is more volatile than any other piece cod…
None of the concerns of concurrency go away because you don't have threads, they go away when you have no multitasking , and NodeJS is a cooperatively multitasking environment (modulo a few minor asterisks). So of course there are still critical sections--a critical section is a set of operations that must have uninterrupted access to a resource in order to maintain a desired level of consistency. If you have to yiel…
There simply is no concurrency in JavaScript, so lock primitives are not solving any problem that JavaScript has.
Can you give an example of some code where you think locks would help you?
Re: V8 adds support for top-level await
#255All this async code without decent locking primitives is leading to a rabbit hole of race conditions... It doesn't matter that it's all single threaded if all your function calls may or may not block and run a bunch of other code in the meantime, mutating all kinds of state. I feel like JavaScript developers of the 2020's are going to relearn the same things the C programmers of the 1990's learn, just a few levels of…
Data races are impossible in JavaScript because it's single-threaded. Race conditions are possible in any language that can do anything asynchronous, which is basically all of them. But the general benefit you get from JS being single-threaded is the fact that any given callback is transactional. No other code will ever come in and mutate state between two regular lines of JavaScript code. Achieving this is pretty mu…
Re: V8 adds support for top-level await
#256Earlier quoted context omitted.
> Even at CPU level, "sequential" instructions aren't Within the context of the argument you are making, this is disingenuous. There's a big pile of transistors which determine whether it is safe to reorder those instructions.
Thar same pile of transistors, with a thick layer of software, determines whether it's safe to proceed a coroutine. const foo = async () { const ice = await freeze(water); const wCream = await whip(cream); const base = await pour(liquor, ice); const cocktail = await put(base, wCream); return cocktail.serve(); } In the above fragment, `freeze` and `whip` may run in any order or in parallel, you don't get to choose. St…
Re: V8 adds support for top-level await
#257Earlier quoted context omitted.
Javascript devs, for all their flaws, understand async programming far, far better than the average C programmer. Indeed, your assertion that we need "locking primitives" to counteract "race conditions" is evidence of that. Yes, JavaScript can have race conditions, but not multi-threaded race conditions that cause resource contention [0]. So what good would locking primitives be? And as a solution to single-threaded…
Here's an example of how you might get a race condition in JS: async function deduct(amt) { var balance = await getBalance(); if (balance >= amt) return await setBalance(balance - amt); } One way to resolve this would be with a mutex to protect the balance during the critical section (which is async). What would you suggest instead?
async function changeBalance(account, amt) {
/*
* BEGIN;
*
* UPDATE accounts
* SET balance = balance - amt
* WHERE id = ${id};
*
* COMMIT;
*/
}
Of course, this is just a mutex in database transaction clothing :)Re: V8 adds support for top-level await
#258Earlier quoted context omitted.
I'll tell you why these languages like Lisp or APL or Ada aren't actually good languages. If they were really good languages, people would not only strongly advocate for them, they would give credibility to their advocacy by writing plenty of great programs in them, even on their own time, because they are very productive in these languages. They would also create best-in-class tooling to further their productivity e…
I disagree with your position that a language is good or not based on how people appreciate or use it. You're trying to tell me garbage such as PHP is one of the best languages there is, effectively. In any case, I can still find examples of these platforms. Emacs is such a platform. For that matter, StumpWM is a platform of sorts. A nice quality of Lisp is making any program extensible with it trivially. As for Ada,…
This is unsurprising.
> You're trying to tell me garbage such as PHP is one of the best languages there is, effectively.
I wouldn't go that far with PHP, it's only used in a certain (lucrative) niche and I can't think of anything great written in it.
Python is a good language that grew organically much in the way that i described.
> As for APL, you don't build platforms or such things in APL. If you don't see the beauty in APL, then that's your loss.
It really isn't a net loss, because I consider the strive for beauty in a program a fool's errand. I get to write useful things in less time by foregoing that ideal.
> In any case, I can still find examples of these platforms. Emacs is such a platform.
Let's suppose that Emacs is a great program. Most languages that are not completely irrelevant have "that one thing" for people to point to. That's not enough. Furthermore, Emacs consists of about 25% of "ugly" C code.
> For that matter, StumpWM is a platform of sorts.
StumpWM? You're quickly running out of Steam here.
> First you claimed people don't build great programs in these languages, which I've shown is false
That's not my claim. My claim is "plenty of great programs" and "best-in-class tooling". A language like Lisp excludes best-in-class tooling or good performance by virtue of its design, so all programs that are written in it have a disadvantage right off the bat.
Ada had some potential here, but it got stuck. I suppose it had something to do with too much of it being proprietary solutions.
> You're conflating extensible software with quality software here.
I don't mean "platform" in the sense of "program that I can extend". I'm talking about the ecosystem and tooling surrounding the language, its "commons", if you will.
> Is it wrong for someone to spend time working on what they view as an ideal and finished program, rather than just writing something that's already been done and requires little thought or effort on their part?
First of all, this is a false dichotomy. Secondly, a program that is ideal and finished but less useful is a poor trade-off. A program that is less ideal and unfinished but has better functionality as a result is, in my view, a better program. More importantly though is not just the one program, but all the programs that can or can not exist, based on the trade-offs you chose.
If you just want to create pieces of art that the very few to appreciate, that's your prerogative. If instead you focus on usefulness however, you can create actual wealth, for yourself and for others.
> It's infinitely harder, I think, to write novel programs...
It is indeed, but it's much harder still to also make them ideal.
> That's what I do with my work. I don't see why you'd look down on that.
I don't look down on it. I just see nothing to look up to.
Re: V8 adds support for top-level await
#259Earlier quoted context omitted.
You moved the goal posts on me. But the solution for your next scenario is actually pretty trivial though isn’t it? You don’t really need what you call locking in a single-threaded world. You just need a state machine.
No, I didn't. That's how a lock works. Only one coroutine (or thread) is allowed to hold it at a time while the others must await their turn. A state machine is a lot more than a boolean variable.
There simply is no concurrency in JS though, so there is no need for locking. There is no way that you would ever "unblock all coroutines waiting for the promise" because you just can't run more than 1 coroutine at a time. So your problem is with ordering, not concurrency and locks are a solution for concurrency.
And the simplest state machine is a boolean variable.
Anyway, I guess if you still disagree then you can go and ask the people who build JS engines why they don't want to add locks. Maybe ask the v8 team - they add stuff that isn't in the spec all the time and they haven't seen a big need for this, so they must know the answer...
Re: V8 adds support for top-level await
#260Earlier quoted context omitted.
For queued ordering instead of unblocking everyone at once you can reassign the Promise. let lock = Promise.resolve() const wait = (callback) => lock = lock.then(() => callback()); Until the callback resolves the lock is held, so you can do: wait(async () => { await step1(); await step2(); // release the lock. });
If the callback throws an error, none of the awaiting coroutines will run, and adding a catch would break the callback error propagation.
Also, nobody said that we need callback error propagation in a priority queue to act the same exact way that callback error propagation works in a straight promise chain... but if you just want to reject all waiters in case of an error, you can do that.
Take a look at sindresorhus' p-queue project - https://github.com/sindresorhus/p-queue - which is about 40 lines of code that take care of queueing exactly the way you want. And it's easy to modify if you want to reject the whole queue in case of an error, which is something that I've done myself in the past. You can see them discussing the possibility of that feature right here - https://github.com/sindresorhus/p-queue/issues/29
Long story short: Your problem is with ordering, not locking.