Prototyped in 10 days sounds more appropriate, then longer road to getting Javascript 1.0 publicly released.
What I'm glad about is that they kept improving the language, especially after ES6 where ECMAScript proposals can be independently evaluated & validated for backwards compatibility.
I heard a whole three weeks but that probably included coffee breaks. And to this day JavaScript remains the best language ever written in less than one month.
I had a professor that claimed to have invented the name ECMAScript. He said that they were arguing about the name for this new standard and weren't moving forward so he proposed a name so awful that they'd have to come back later to change it, so the argument could be put on hold for the time being. Then they never came back to fix it.
lol, I did that with an internal tool once. It actually worked in that case - the name was changed. Although the "so terrible it couldn't exist" name persisted in some dark corners for several years.
A similar thing happened at a company I worked for in the '80s, a 68k based Unix workstation maker named Callan Data Systems, named after David Callan who was one of its founders.
There were two other founders and they were all equal partners, so I asked one of them why Callan was the one it was named after.
What happened was that they had been unable to agree on a name all throughout the early stages of starting the company. They got to the point where they really need to incorporate to continue, but still could not agree on a name.
Tempers were rising and they decided to step away for a few days to calm down, and during that time two of them went out of town for a hunting trip. Callan stayed home.
When the other two got back Callan told them that he'd incorporated with a temporary name, which they could change when they finally thought of a real name they liked. The other two were annoyed, but agreed that this was better than having everything be on hold because they could not incorporate.
That temporary name was "Callan Data Systems" and they never did come up with a replacement, and stopped trying when it had been so long that changing the name would have been a pain.
> Originally this was supposed Scheme, but then Netscape signed a deal with Sun and agreed to make it more "Java-like".
Yes I know it's cliche at this point to mention it. And yes it could've had some unknown negative butterfly effect type of thing, but man I really would have loved to have seen where things would be now if Sun hadn't influenced this.
People use JS over other languages because they have no choice (transpile to JS languages are relatively rare, and TypeScript only succeeded because it's a superset of JS), I'd imagine Scheme would be treated the same way.
Languages with Java-like syntaxt are much more popular than LISPs in general even not taking JS into account. I think it’s just more intuitive to parse it in human brain, at least to me.
What is most intuitive to you is what you're used to. There's a lot of people that find Lisps syntax intuitive, and becoming familiar with it is mostly just part of the process of using it. All programming languages look foreign to the untrained eye.
Languages with Java-like syntax are taught in schools, and Lisp typically isn't.
I've written some Lisp and I don't find the syntax hard to read, so much as my unfamiliarity with the language itself (what does cons do? What kind of args does it take?).
Plus the occasional cluster migraine when I decide to write a macro, knowing that I'm lucky when regular code runs right the first time. Not really a fault of Lisp, I'm sure me trying to write C++ templates would end about the same.
> Languages with Java-like syntax are taught in schools, and Lisp typically isn't.
Er, my experience is that Lisp or Scheme is taught in literally every CS course out there. Not high-school maybe, but then again in high-school you typically don't get Java either - maybe Scratch, maybe Python.
I know on HN it's fashionable to be pro-LISP, but "it's not taught" is not one of the reasons LISP is not popular.
It wasn't on my curriculum, and I've only worked with one person who was remotely familiar with Lisp.
I've worked with more people that know Haskell than Lisp (though that seems like an outlier, I would guess Lisp/Scheme is still more popular than Haskell).
It's totally possible that I'm an outlier or that it's regional, but I haven't seen any indication that Lisp is commonly known.
Disagree. I think JS is ubiquitous in part because the language maintainers are willing to adopt new syntax and borrow concepts from other languages, and therefore keep the language modern and accessible.
For example, CoffeeScript was everywhere about 10 years ago. If someone had told me then that in 5 years it would be dead, and in 10 years new devs would not have even heard of it, I wouldn’t have believed it. CoffeesScript died largely because JS adopted most of the innovations Coffee brought to the table in ES2015/ES6, thus Coffee became unnecessary.
I didn’t say otherwise. I’m actually much more proficient in Clojure than I am in JS in part for that reason.
Still, JS has come a long way in the past 10 years, which is impressive. When I need to write JS, I’m glad the days when I needed to use Underscore just to get map, reduce, etc. are long gone.
It's debatable the extent to which JavaScript contributed to the ubiquity of the web for interactive applications, versus the extent to which interactive web applications contributed to the ubiquity of JavaScript.
But regardless of the historical reasons, JavaScript is now an extremely popular programming language for non-web applications.
Scheme is around today, and there are some pretty good implementations. But few people use it. Sometimes I suspect there are more Scheme implementations than Scheme users.
Lisp-style programming with s-expressions is just not very popular. Pure (or "pure-ish") functional programming in general just isn't.
I know some people really like functional programming and/or scheme, but the reality of the matter is that this never has been (and I suspect never will be) a mainstream opinion.
Functional programming is the Black Metal of programming. It's great and all, but will always be for a relatively small and niche audience.
And that's okay. Not everything needs to be large.
I think it would be adopted exactly as widely as JavaScript is. People choose JavaScript because it is supported by the browser, not because they think it has a beautiful syntax. If some other language has been supported instead (whether VBScript or Scheme or whatever), people would use that.
Semantic markup languages were niche until the web happened. Objective-C was a weird niche language until the iPhone app boom. People learn the languages they need to learn.
I was thinking about this recently in a completely different context. Java itself is actually not a bad language for what it tries to be: an easier to use ("safer") C++. It makes for a better "object oriented C" than C++ or Objective-C did.
Everywhere it really went wrong was when Sun got involved. J2EE, and especially EJB, was a complete waste and continues to create problems to this day - the awful but inescapable Spring "framework" was actually a replacement for the equally awful EJB architecture and creates the same bloat but without the licensing costs.
I'm separating James Gosling's creation of the language from everything the rest of the company did with it afterwards (although I guess he was working there at the time so technically he was "Sun", too).
My preferred language is Java. I had to teach myself starting around 1998. But for whatever reason I still haven't learned Spring. I haven't needed it for any of my work.
Sort of the same here. I've read about Spring and built some toy apps to learn more, but I always found myself asking why I would want something like that in my stack if it could possibly be avoided.
I agree, Id almost love to see a "For All Mankind"-esque show about it - an alternative history where browsers ran on lisp. I could imagine that there would have been so many things that would be wildly different - not the least of which node and typescript being around at all, much less some of the most popular languages available. I think the web and browsers for it was going to bring whatever language it chose to the forefront, no matter what it was. Back then I would have written anything - we certainly were not _choosing_ javascript!
Three decades ago I was similarly overjoyed to discover that Scheme was finally going to have a useful application beyond illustrating SICP and writing koans to amuse myself, because DSSSL was on the cusp of evolving into the last document styling language anyone would ever need.
Unfortunately following an incident with a broken Lisp machine, a liquid lunch, and an unlicensed particle accelerator, I became trapped in a parallel universe where the HTML ERB anointed CSS by mistake during a drunken night out in Oslo.
The fundamental concept of CSS (best revealed by H.W.Lie's thesis IMO¹) was to create a rich and versatile and non-Turing-complete set of structural selectors in lieu of DSSSL's recursive logic, and to allow styles to overlay one another; two design choices that only by the application of gallons of irony can explain why most web pages are composed of a bunch of nested DIV elements with hashed IDs, overburdened class attributes, and assets compiled into static files.
> Unfortunately following an incident with a broken Lisp machine, a liquid lunch, and an unlicensed particle accelerator, I became trapped in a parallel universe where the HTML ERB anointed CSS by mistake during a drunken night out in Oslo.
Mostly though you're upset because respectable computer scientists didn't get invited to those sorts of parties.
CSS is a classic case of road to hell paved by good intentions.
"We'll have one style for the browser and one for printing!" - but turns out that nobody really gives a crap about printing, and when they do they want stuff printed exactly like it looks on screen.
"Forget tables, we'll have stuff floating around the screen!" - but turns out that there are more requirements for positioning rules that can be contained in anyone's philosophy.
> I agree, Id almost love to see a "For All Mankind"-esque show about it - an alternative history where browsers ran on lisp
I've thought about something similar, but for hardware--what if some early hardware design choices had went in a different way?
For example consider cathode ray tube (CRT) displays. A different choice by the CRT pioneers and we might have ended up with CRTs that scan outward in a spiral from the center, instead of scanning in a series of stacked left to right rows.
That would make bit mapped displays a lot more complicated. God help the programmer who has to write BITBLT for a spiral scan display.
One of the biggest warts is the difference between the == and === operators. Eich attempted to alter the behavior of == in order to fix it, but was not allowed to ship the change for fear of backwards incompatibility, forcing him to add a new operator instead. To this day, recommended linter settings disallow use of the == operator entirely.
`==` and `!=` are still quite handy when you don't want to deal with the distinction between `null` and `undefined`, which is almost always what you want.
If you do this, you need to think through all the possible types for the comparators and how type coercion will affect the expression. For example, `0 == ''`, `[] == ''`, and `[] != []` are all `true`. If you're using typescript to get guarantees about the input types, maybe that's a good use case for using type coercion intentionally.
I find that I really appreciate the explicit rather than the implicit comparisons (requiring `===` in js), especially picking up a new program or coming back to one after some time away. I view it like a database - do I really want multiple ways to show a value is empty? For something like a Boolean you have: `false`, `true` and `null` as valid values (trilean?) that now have to be handled.
Actually, I was surprised to learn last week that the `eqeqeq` rule that disallows `==` is not in ESLint's recommended set: https://eslint.org/docs/latest/rules/
(And I immediately enabled it for our codebase. Generally I like to just rely on the recommended non-stylistic rules, but this is such an easy footgun that everybody on my team already defaulted to adhering to, that I made an exception.)
As a junior JS dev curious to learn more, can someone give me a starting point into the “warts”? What are they, why are they considered bad, how do other languages solve these problems?
And hoisting with var, of course those are not relevant to modern JS any more. One other thing was the "this" binding in callbacks and events, if anyone still remembers doing var self = this; , luckily we have arrow functions now and class syntax for methods.
- No control over integer type. Everything is a double, except that it sometimes behaves like int for bitwie operation. You lose precision easily and silently. BigNum support is ugly.
- Standard library is one of the worst among all languages, it's inconsistent and missing many basic functions.
- Implicit type casting means you are better off always using === and never relying on truthiness (ie. in "if (...)" better make sure this ... evaluates to true or false, not {}, null, etc, or else you will be surprised by 0).
- We have both exceptions and 2 special marker types (null, undefined). Different libraries will use different methods to signify errors. See Rust for how to do this well.
- Prototype based inheritance sometimes leaks as an abstraction. The only languages I know of that use prototypes are JS and Lua.
The solution to the poor standard library in my opinion is for someone like NPM to step up and provide the defacto language library. It will help in reducing the sheer volume of JavaScript dependencies to only one library.
It's pretty common for embedded languages to not include big batteries included standard libraries. And at its core, JS is designed and optimized as an embedded language (to extend the functionality of a browser). That's why on the frontend the "standard library" are the DOM and window APIs provided by the browser.
The idea that it needs a better standard library is deeply tied to the idea that it should be used as an applications language, but that's actually kind of a recent idea with the advent of runtimes like Node and later Deno and Bun. And all of these do include bigger standard libraries.
I think part of the reason JS has become so popular as both an embedded and application language is that it doesn't have a standard library that needs to be shipped to all embedders/implementations. That's what Java does. And Java lost a lot of ground to JS over the years.
But only Javascript was embedded right into the browser and that is why it was extremely difficult to kill it unlike all the other technologies available as add-ons.
> We have both exceptions and 2 special marker types (null, undefined). Different libraries will use different methods to signify errors. See Rust for how to do this well.
This is in part because JS’s exceptions support is the worst: catch clauses can’t be filtered by type so you have to catch/filter/rethrow, and before ES6 subtyping Error was essentially impossible.
So even if you are fine with exceptions, you don’t want to use them in JS. Even more so before async proper as they obviously did not work correctly through callback chains.
Regarding implicit type conversion: Arguably, this is the way all scripting language went about that time, and, notably, shell scripting, as well. (Meaning, it was pretty much the expected behavior for a language of that kind. Hence, the appeals for adding this to JS, as well.) JS was much like a shell for the web browser window and not meant to be a full-fledged application language. And, if you really needed it, you could still check the very nature of any value by the use of `typeof`.
The same applies to the "standard library", which is really just a collection of helper functions under the umbrella of a few top-level built-in objects to keep the core language clean.
I'd rather blame the generations of devs implementing add-ons and syntactic sugar according to the fashion of the day and mimicking their respective favorite language, which adds loads of inconsistencies to the various extensions of the language (often leading to duplicate mechanisms and implementations), depending on when it was done. So there is no common way of communicating with these interfaces and no implicit design philosophy (it may be JFX-style, callback based, a promise, functional, whatever). This is even true for the core language, e.g., arrow-functions breaking the basic convention of arguments always coming as a list.
Other languages have certain ways of dealing with coding tasks that are quirky and weird as well. They are considered bad when they have unexpected side effects -- or cause bugs that are difficult to track down and diagnose.
A common way to fight these issues is to use a linter -- something that runs when the code is built and warns you about lines of code that should most likely be changed or might be error prone.
Off the top of my head, numbers get stringified when used as keys in objects. === and !== are almost always what you want instead of == and !=. It's generally too eager to stringify values when the programmer is doing something a bit suspect. For some use cases, it's also annoying that you get undefined instead of an exception when you attempt to access a missing object property, along with undefined == null being very annoying for similar reasons.
I used to work on executing JavaScript as part of Google's indexing infrastructure. Some webmasters saw tons of errant URLs with "undefined" and "NaN" in them when Google first started crawling the URLs discovered via JavaScript. It would have been too much work for me to implement full data flow dependency tracking in SpiderMonkey, so I modified the typecast code to perform data flow analysis at the type level. If undefined was ever cast to Number, then all numbers were suspect. If undefined was ever cast to String, then all Strings were suspect. If Number was suspect and NaN was ever cast to String, then all Strings were suspect. We stopped keeping track of generated URLs if Strings became suspect. I put in a few heuristics to cover some common patterns to avoid making things overly suspect, and that seemed to work pretty well. In any case, it would have been better from a dynamic analysis standpoint (and easier on webmasters and their webservers) had JavaScript been more liberal in throwing exceptions instead of trying to limp along after hitting an error.
A lot of things have been fixed, but historically I can recommend to watch some youtube videos by Douglas Crockford, he wrote a book "JS, the good parts". At the time JS was universally hated (this was more than a decade ago), esp. by serious programmers doing Java, C# and the like. So much so that companies created languages and tools that generate HTML & JS, so the "real devs" didn't have to touch JS (one example is the Google Web Toolkit).
Netscape had market dominance at the time so Internet Explorer had to keep bug-for-bug compatibility with Netscape to keep up. Given the amount of bugs and the lack of documentation of JS, this must have been quite frustrating for MS who was used to calling the shots.
88 comments
[ 29.0 ms ] story [ 895 ms ] threadWhat I'm glad about is that they kept improving the language, especially after ES6 where ECMAScript proposals can be independently evaluated & validated for backwards compatibility.
There were two other founders and they were all equal partners, so I asked one of them why Callan was the one it was named after.
What happened was that they had been unable to agree on a name all throughout the early stages of starting the company. They got to the point where they really need to incorporate to continue, but still could not agree on a name.
Tempers were rising and they decided to step away for a few days to calm down, and during that time two of them went out of town for a hunting trip. Callan stayed home.
When the other two got back Callan told them that he'd incorporated with a temporary name, which they could change when they finally thought of a real name they liked. The other two were annoyed, but agreed that this was better than having everything be on hold because they could not incorporate.
That temporary name was "Callan Data Systems" and they never did come up with a replacement, and stopped trying when it had been so long that changing the name would have been a pain.
Yes I know it's cliche at this point to mention it. And yes it could've had some unknown negative butterfly effect type of thing, but man I really would have loved to have seen where things would be now if Sun hadn't influenced this.
I've written some Lisp and I don't find the syntax hard to read, so much as my unfamiliarity with the language itself (what does cons do? What kind of args does it take?).
Plus the occasional cluster migraine when I decide to write a macro, knowing that I'm lucky when regular code runs right the first time. Not really a fault of Lisp, I'm sure me trying to write C++ templates would end about the same.
Er, my experience is that Lisp or Scheme is taught in literally every CS course out there. Not high-school maybe, but then again in high-school you typically don't get Java either - maybe Scratch, maybe Python.
I know on HN it's fashionable to be pro-LISP, but "it's not taught" is not one of the reasons LISP is not popular.
I've worked with more people that know Haskell than Lisp (though that seems like an outlier, I would guess Lisp/Scheme is still more popular than Haskell).
It's totally possible that I'm an outlier or that it's regional, but I haven't seen any indication that Lisp is commonly known.
For example, CoffeeScript was everywhere about 10 years ago. If someone had told me then that in 5 years it would be dead, and in 10 years new devs would not have even heard of it, I wouldn’t have believed it. CoffeesScript died largely because JS adopted most of the innovations Coffee brought to the table in ES2015/ES6, thus Coffee became unnecessary.
Still, JS has come a long way in the past 10 years, which is impressive. When I need to write JS, I’m glad the days when I needed to use Underscore just to get map, reduce, etc. are long gone.
But regardless of the historical reasons, JavaScript is now an extremely popular programming language for non-web applications.
Lisp-style programming with s-expressions is just not very popular. Pure (or "pure-ish") functional programming in general just isn't.
I know some people really like functional programming and/or scheme, but the reality of the matter is that this never has been (and I suspect never will be) a mainstream opinion.
Functional programming is the Black Metal of programming. It's great and all, but will always be for a relatively small and niche audience.
And that's okay. Not everything needs to be large.
Semantic markup languages were niche until the web happened. Objective-C was a weird niche language until the iPhone app boom. People learn the languages they need to learn.
Was a good stab at things too but went nowhere sadly.
I was thinking about this recently in a completely different context. Java itself is actually not a bad language for what it tries to be: an easier to use ("safer") C++. It makes for a better "object oriented C" than C++ or Objective-C did.
Everywhere it really went wrong was when Sun got involved. J2EE, and especially EJB, was a complete waste and continues to create problems to this day - the awful but inescapable Spring "framework" was actually a replacement for the equally awful EJB architecture and creates the same bloat but without the licensing costs.
Java is a Sun product in the first place; i'm misunderstanding what you mean.
Unfortunately following an incident with a broken Lisp machine, a liquid lunch, and an unlicensed particle accelerator, I became trapped in a parallel universe where the HTML ERB anointed CSS by mistake during a drunken night out in Oslo.
The fundamental concept of CSS (best revealed by H.W.Lie's thesis IMO¹) was to create a rich and versatile and non-Turing-complete set of structural selectors in lieu of DSSSL's recursive logic, and to allow styles to overlay one another; two design choices that only by the application of gallons of irony can explain why most web pages are composed of a bunch of nested DIV elements with hashed IDs, overburdened class attributes, and assets compiled into static files.
[1] https://www.wiumlie.no/2006/phd/css.pdf
Mostly though you're upset because respectable computer scientists didn't get invited to those sorts of parties.
"We'll have one style for the browser and one for printing!" - but turns out that nobody really gives a crap about printing, and when they do they want stuff printed exactly like it looks on screen.
"Forget tables, we'll have stuff floating around the screen!" - but turns out that there are more requirements for positioning rules that can be contained in anyone's philosophy.
Etc etc...
“The Web That Never Was”: https://youtu.be/8JOD1AQGqEg
I've thought about something similar, but for hardware--what if some early hardware design choices had went in a different way?
For example consider cathode ray tube (CRT) displays. A different choice by the CRT pioneers and we might have ended up with CRTs that scan outward in a spiral from the center, instead of scanning in a series of stacked left to right rows.
That would make bit mapped displays a lot more complicated. God help the programmer who has to write BITBLT for a spiral scan display.
Or maybe Flash with ActionScript would have won. ;)
We might have had web assembly earlier
https://archive.apache.org/dist/
While I have never been a Java fan, it is so ubiquitous that time spent learning it will never be wasted time.
(And I immediately enabled it for our codebase. Generally I like to just rely on the recommended non-stylistic rules, but this is such an easy footgun that everybody on my team already defaulted to adhering to, that I made an exception.)
- No control over integer type. Everything is a double, except that it sometimes behaves like int for bitwie operation. You lose precision easily and silently. BigNum support is ugly.
- Standard library is one of the worst among all languages, it's inconsistent and missing many basic functions.
- Implicit type casting means you are better off always using === and never relying on truthiness (ie. in "if (...)" better make sure this ... evaluates to true or false, not {}, null, etc, or else you will be surprised by 0).
- We have both exceptions and 2 special marker types (null, undefined). Different libraries will use different methods to signify errors. See Rust for how to do this well.
- Prototype based inheritance sometimes leaks as an abstraction. The only languages I know of that use prototypes are JS and Lua.
The idea that it needs a better standard library is deeply tied to the idea that it should be used as an applications language, but that's actually kind of a recent idea with the advent of runtimes like Node and later Deno and Bun. And all of these do include bigger standard libraries.
I think part of the reason JS has become so popular as both an embedded and application language is that it doesn't have a standard library that needs to be shipped to all embedders/implementations. That's what Java does. And Java lost a lot of ground to JS over the years.
This is in part because JS’s exceptions support is the worst: catch clauses can’t be filtered by type so you have to catch/filter/rethrow, and before ES6 subtyping Error was essentially impossible.
So even if you are fine with exceptions, you don’t want to use them in JS. Even more so before async proper as they obviously did not work correctly through callback chains.
The same applies to the "standard library", which is really just a collection of helper functions under the umbrella of a few top-level built-in objects to keep the core language clean.
I'd rather blame the generations of devs implementing add-ons and syntactic sugar according to the fashion of the day and mimicking their respective favorite language, which adds loads of inconsistencies to the various extensions of the language (often leading to duplicate mechanisms and implementations), depending on when it was done. So there is no common way of communicating with these interfaces and no implicit design philosophy (it may be JFX-style, callback based, a promise, functional, whatever). This is even true for the core language, e.g., arrow-functions breaking the basic convention of arguments always coming as a list.
- Implicit type conversion
- Javascript null handling
- "all numbers are floats"
Other languages have certain ways of dealing with coding tasks that are quirky and weird as well. They are considered bad when they have unexpected side effects -- or cause bugs that are difficult to track down and diagnose.
A common way to fight these issues is to use a linter -- something that runs when the code is built and warns you about lines of code that should most likely be changed or might be error prone.
I used to work on executing JavaScript as part of Google's indexing infrastructure. Some webmasters saw tons of errant URLs with "undefined" and "NaN" in them when Google first started crawling the URLs discovered via JavaScript. It would have been too much work for me to implement full data flow dependency tracking in SpiderMonkey, so I modified the typecast code to perform data flow analysis at the type level. If undefined was ever cast to Number, then all numbers were suspect. If undefined was ever cast to String, then all Strings were suspect. If Number was suspect and NaN was ever cast to String, then all Strings were suspect. We stopped keeping track of generated URLs if Strings became suspect. I put in a few heuristics to cover some common patterns to avoid making things overly suspect, and that seemed to work pretty well. In any case, it would have been better from a dynamic analysis standpoint (and easier on webmasters and their webservers) had JavaScript been more liberal in throwing exceptions instead of trying to limp along after hitting an error.
Yeah, sure, the kernel was functional. But just about everything we think of as Linux came later from thousands of contributors.
Emphasis mine