Live data from Hacker News

Douglas Crockford on JavaScript

digest.browsertech.com

151–160 of 202 posts

Re: Douglas Crockford on JavaScript

#151
> we’d get new computer languages about every generation.

> accumulated complexity we’ve piled on top of bad foundations

OTOH when we get new computer languages, they usually start really simple as a sort of protest against the "old" complexity and then spend the next few decades shoehorning back in all the things they left out to keep it simple but that it turns out we actually needed.

Re: Douglas Crockford on JavaScript

#152
post #81

Earlier quoted context omitted.

> It's just that noone has been able to replicate that kind of success [of Rust's and Go's achievements] in the web-based frontend space. While it's easy to dog on Javascript, it's also necessary to consider what Javascript does right. The main thing that comes to mind is JS' async-everything, async-by-default, and first class async abstractions (like the Promise). Not necessarily something you want all the time, but…

What JavaScript does right, is to have an installed VM on basically every computer out there. If you are building a consumer focused thing, it is hard to argue for any other installation method. Especially when you consider you can remove the need to track multiple deployments in the same way, since you can basically force an update to all users.

Microsoft had VBScript installed on >90% of all browsers at one time. Google almost installed Dart by default in Chrome and then walked it back. Java was installed on all browsers for a decade, but no one wanted it. WebAssembly allows for languages like Rust to be used, but its adoption is still very niche.

JavaScript lives on. It's not just inertia. IE for example supported multiple languages at the same time. As a lingua franca, JS is simply better than the alternatives.

Python is subjectively cleaner than JS, but it isn't sufficiently better to warrant replacing JS, especially after JS started becoming more Pythonic. Lua is arguably a step backwards. Go adds a necessary compile step. Folks already gave Java a shot. C/C++ was a hard-learned lesson after ActiveX regarding web security. Perl ain't gonna be it obviously. Rust has a much too steep learning curve for the vast majority of web developers to tolerate. Ruby is slower and also not sufficiently better.

I know folks don't like to hear it, but JavaScript is nowhere near as bad as folks like to go on about it. In fact it's so flexible, an entire ecosystem rose up around it on the server side more than a decade after its client-side debut. If JS were really that bad, no one would adopt it for other areas if they didn't have to. It is familiar and gets the job done. We only highlight its shortcomings because we've had almost 30 years to pick it apart and dissect it.

Google could team up with Apple and make Swift a supported language. Within 2 years, it would be on >90%+ of all devices. Maybe 95%. And it wouldn't matter. Sure, a bunch of folks would use it, especially if they were Apple devs. But the vast majority would ask, "What would this new language give me that JS can't do? Is it actually worth rewriting apps and retraining my staff?" Honestly, the answer is 'no'.

Because JS really isn't bad. It has warts (though many/most of them due to the DOM rather than the language). It has legacy. But after 30 years, it's still doing surprisingly well at both speed, flexibility, and the ability to evolve.

Re: Douglas Crockford on JavaScript

#153
post #142

Earlier quoted context omitted.

> It's just that noone has been able to replicate that kind of success [of Rust's and Go's achievements] in the web-based frontend space. While it's easy to dog on Javascript, it's also necessary to consider what Javascript does right. The main thing that comes to mind is JS' async-everything, async-by-default, and first class async abstractions (like the Promise). Not necessarily something you want all the time, but…

"But consider something like this (JS) using WaitGroups in Go:" Sure, though if this is something you're doing a lot of it's not hard to abstract out. However, let me put on the other side of the balance the sheer staggering quantity of code there is out there that just "await"s everything in line as if they were writing some version of Go that required you to specify every function that could potentially be async, b…

Promise.all, Promise.race, and Promise.allSettled are a non-trivial amount of my await calls. Also, while you may consider "await" noise, I consider it signal. I want to know when the execution queue has a break 100% of the time. Implicit await would make ordinary JS code a nightmare to debug.

Contrast this with Go where you must synchronize shared resources. Yes, the go-routine model allows relatively simple concurrency. However concurrency management is simply not a concern in JS-land. Yes, JS can be optimized so that more happens in parallel, but deadlocks can happen. Multiple writers to the same object can't happen. Passing data between threads enforces ownership and visibility out of the box. JS is bulletproof from a developer standpoint, which is a boon to security and absolutely, positively required in an environment where you're executing random code from random authors on the internet.

JavaScript really doesn't get enough credit for what it's accomplished.

Re: Douglas Crockford on JavaScript

#154
post #115
post #113

Earlier quoted context omitted.

I disagree. I'd take JS-style promises over trying to manage Futures in ForkJoinPools or thread pools any day. Being able to write async expressions in parallel by default means even junior devs take advantage of parallelism. I've seen plenty of code written in Java and Ruby where multiple network and DB requests are made in serial despite having no dependency on each other. The usual reason is that there's just a lo…

I have also found Promises very hard to reason about at times: "okay, so I have some code here, and when exactly is this run?" can be a difficult question to answer with Promises. Part of that is inherent in async code, but part of that is also because IMHO Promises make it harder than it needs to be. I never really used Java, but I have used Ruby and Python (IIRC Python's APIs were modelled on the Java ones) and I a…

My code is running My code is accessing another resource (storage, network, etc.) It's really not that complicated. If you're surprised by the presence of absence of a Promise, you might want to take a moment to understand what is being processed. There's a good chance there's a gap there that extends beyond a simple keyword in JS.

Re: Douglas Crockford on JavaScript

#155
post #148
post #113

Earlier quoted context omitted.

I disagree. I'd take JS-style promises over trying to manage Futures in ForkJoinPools or thread pools any day. Being able to write async expressions in parallel by default means even junior devs take advantage of parallelism. I've seen plenty of code written in Java and Ruby where multiple network and DB requests are made in serial despite having no dependency on each other. The usual reason is that there's just a lo…

Async doesn't give you parallelism by default though, you just get concurrency. You don't get parallelism without using Workers.

And workers get you isolation, no shared memory. You must explicitly pass data ownership from one thread to the next. (And I consider all of that a good thing.)

Re: Douglas Crockford on JavaScript

#156
post #133

Earlier quoted context omitted.

> It's just that noone has been able to replicate that kind of success [of Rust's and Go's achievements] in the web-based frontend space. While it's easy to dog on Javascript, it's also necessary to consider what Javascript does right. The main thing that comes to mind is JS' async-everything, async-by-default, and first class async abstractions (like the Promise). Not necessarily something you want all the time, but…

Async in interface by default was a mistake and led to a ton of pain. Actually-async-under-the-hood is fine. See: how much JS is rightly and justifiably littered with "await" on seemingly almost every line, now that that's an option. It's downright comical to look at, and as clear a sign of mis-design in a language/runtime as you can get. Nine times out of ten (maybe more...) you just need to treat all that async stu…

> It's downright comical to look at, and as clear a sign of mis-design in a language/runtime as you can get.

That's your opinion. Some of us prefer to know when a call is I/O-constrained and when the execution queue is being interrupted. JS had fearless concurrency before it was cool.

When was the last time you heard of a JS program in a thread deadlock under load (other than a VM bug)? Never. It can get caught up in an infinite loop like any language, but that's not deadlocking. Because the language doesn't allow it. Not "makes it easier to avoid". Straight up doesn't allow it. That's no small thing, and it's not something Go can claim.

Re: Douglas Crockford on JavaScript

#157
post #115

Earlier quoted context omitted.

I have also found Promises very hard to reason about at times: "okay, so I have some code here, and when exactly is this run?" can be a difficult question to answer with Promises. Part of that is inherent in async code, but part of that is also because IMHO Promises make it harder than it needs to be. I never really used Java, but I have used Ruby and Python (IIRC Python's APIs were modelled on the Java ones) and I a…

> I have some code here, and when exactly is this run? If there are `await` keywords previously in the function, then the line you're looking at will run after these async calls are done. Otherwise it'll run ASAP. Is there something else to it?

People often get confused because they expect `await` to sequence promise resolution too. For example

    const example = async () => {
        const ifError = Promise.reject("something went wrong")
        const value = await someOtherPromise()
        await (valueIsOk(value) ? runNextStep(value) : ifError)
    }
will always throw.

Re: Douglas Crockford on JavaScript

#158

Earlier quoted context omitted.

What exactly is "broken" about the foundation of JS? I hear this all the time and people can never back it up. It is extremely performant for a scripting language, it is easy to debug, and it works in many scenarios. People try too hard to be contrarian. Same thing happened with PHP and many other languages.

How performant a scripting language ends up being is partly due to a couple of fundamental design choices, and partly just due to investment. The fact JS has very limited interaction between threads makes a JIT much easier to write. In terms of design there’s a lot of annoying things round equality, operators, and coercion which makes everything just that little bit harder to keep in your head. The standard library a…

> The fact JS has very limited interaction between threads makes a JIT much easier to write.

And easier for developers to write and reason about. This is not small thing. Re-entrant code by default (and basically by mandate) eliminated deadlocks in even a beginner's code. Do you understand how amazing a language is than encourages concurrency and allows parallelism with any fear of deadlocks or explicit atomism?

Re: Douglas Crockford on JavaScript

#159

He is promoting an "actor language" to replace JavaScript. https://www.crockford.com/misty/

And it's not clear it would be worth the retooling/training on the UI-side of things. The actor model is great for massive concurrency, which simply isn't a primary or even a secondary concern for 99.9% of client-side code. There's a reason why Go has such a huge following in the server space but a deafening silence of folks wanted it available in browser UI code.

Re: Douglas Crockford on JavaScript

#160
post #148
post #113

Earlier quoted context omitted.

I disagree. I'd take JS-style promises over trying to manage Futures in ForkJoinPools or thread pools any day. Being able to write async expressions in parallel by default means even junior devs take advantage of parallelism. I've seen plenty of code written in Java and Ruby where multiple network and DB requests are made in serial despite having no dependency on each other. The usual reason is that there's just a lo…

Async doesn't give you parallelism by default though, you just get concurrency. You don't get parallelism without using Workers.

Fair, I should've been more careful with the way I worded that. The common example I was highlighting was concurrent network IO requests that effectively resolve to parallel work that runs on different nodes. With a service oriented architecture, this can be the norm rather than the exception.
Post reply on HN