JavaScript is the C++ of the Web
pointersgonewild.com
pointersgonewild.com
An AST is used because it allows significantly smaller download sizes, which is quite important on the web, more details here:
https://github.com/WebAssembly/design/blob/master/AstSemanti...
WebAssembly is in a different situation than gcc, clang, etc. It makes sense for LLVM IR, for example, to have a CFG, as it is a compiler IR meant for optimization. But WebAssembly binaries are meant to be distributed over the web and instantiated as quickly as possible.
> This decision was clearly made to try and simplify the job of WebAssembly VM implementers, at the expense of everyone else.
I don't think that is the reason at all. In fact it adds work for those people to handle an AST. But the work is justified by the startup speed benefits that it brings to the web platform.
Besides, converting a CFG to a high-level AST is a complete non-problem these days.
[1] http://dl.acm.org/citation.cfm?doid=2048147.2048224 [2] https://github.com/kripken/emscripten-fastcomp/blob/master/l...
The only thing that matters in my opinion is generators and (in ES7), async/await. This is a shift we've been seeing in many languages and I think actually tangibly solves a real problem in a transformative way. By that I mean, people will actually think about problems differently. Especially in JavaScript where everything is asynchronous, you need first class support of asynchronocity.
There are a bunch of feature I "like" in ES6 but are ultimately useless in my opinion. Arrow functions are great, but could 1) be implemented in a transpolar, and 2) unfortunately behave different with regard to this and thus make the language even harder to understand (why did all my code break when I switched out the arrow function for a normal inline function?).
Classes are horrible in my opinion, especially if they start inspiring people to use instanceof, which is a broken feature in Javascript (and hence why we need things like Array.isArray). Due to the fact that in JavaScript you will often have code from different contexts, you can't rely on these checks, and the old-style JS programming encourages you to use feature detection, whereas now you will think you can do something like this. The species properties (so map returns the right thing when you subclass Array for example), is even more complex. The fact that I can subclass Function is a bit absurd. The fact that subclassing Object, vs subclassing null, vs no subclass will be a lot of fun to understand.
Let scope is fine I guess, I honestly never thought this was a big deal (coming from C and having to make the switch). It was of course implemented with TDZ which makes it incredibly hard to write in a transpiler, so now you have situations where the transpired code will work but once real let is added your code will break.
Understanding ES5 async callbacks requires very little conceptual understanding -- you need to understand run-to-completion and the event loop (and I guess the idea of higher-order functions), but otherwise it's straightforward.
Understanding ES2016 async/await keywords require you to understand all of that, plus ES2015 promises, ES2015 generators, and how they're all orchestrated together to implement async/await. The code looks simpler, but understanding what's really happening is a lot harder.
It's kind of important to understand promises to use await/async affectively. I love the easier to read/follow code though.
Why is that an argument against a new feature? Should we stop developing transpilable features? This creates fragmentation and a jungle of compile-to-JavaScript languages order of magnitude bigger than what we've got now. The more languages you have the more effort is required for having good tooling, which is already lacking.
> unfortunately behave different with regard to this and thus make the language even harder to understand
In my opinion they make the language more easier to understand, as the this keyword becomes rarely required, the code becomes more readable and you'll get rid of weird var that = this; or .bind tricks.
> Classes are horrible in my opinion
Classes are pretty nice. It's a syntax sugar which is nicer and easier to understand than using functions and prototypes.
> Let scope is fine I guess, I honestly never thought this was a big deal
It eliminates a certain class of bugs without a downside. I never use var anymore.
I agree with the general point that ES6 seems to have focused a lot on not that important syntax sugar.
I actually think that this syntax sugar is the opposite of a solution. It has always been tricky getting developers coming in from other languages (mainly C-like, and Java-like) to understand that JS is NOT an object-oriented language, but in fact is a prototypal language.
By adding the class keyword, I think this only confuses those users further.
It's both.
Both languages have warts, but JS is a small enough language (at least in the ES5/ES5+Typescript world I was working in) that the warts felt finite. The first couple months were full of surprises, but after that I felt like I had a good grasp on the language, and knew when it was going to bite me.
No such luck with C++, however. It still seems like there are several times per week where I'm surprised by some new way the language can screw me over, like non-virtual inheritance, or a newly discovered subtlety in the way includes are processed.
Another benefit of JS - since the language is interpreted, build times tend to be much lower, and debugging tends to be much easier than C++.
EDIT: Another benefit of JS - people like to give JS devs grief for all of the OSS frameworks they create, but in the C++ world every major company has built their own, in-house, closed-source implementations of the same shit. I'd love to know how many different implementations of a linked list in C++ exist in the wild today.
Why isn't the STL linked list enough?
Intrusive lists also allow an object to be in multiple lists at the same time (usually ones with different purposes) by having multiple sets of prev/next pointers.
http://www.boost.org/doc/libs/1_58_0/libs/multi_index/doc/re...
As a bonus the ownership semantics are clear and memory management remains trivial. Intrusive lists are useful, i'll grant you, but they'll always be a last resort for me. Especially if you're implementing them yourself.
* there is no subtlety in the way includes work, they are simply merged into the file.
* non-virtual inheritance is just normal inheritance. In case you meant non-virtual functions when using inheritance, that is also a very basic part of C++.
As for the list, there's been a std::list for a very long time now. If your project is using custom lists then they either needed something very specific or are very very old. In that case, you should not criticize the language IMO. JS however can very well be lambasted, because new JS frameworks pop up often nowadays and they do exactly the same things in slightly different ways in 2015, not in 1997.
What made asm.js a breakthrough was that vendors couldn't kill it by ignoring it - it's just Javascript, so it doesn't need explicit support to run, so ignoring it just hurts you in competitive perf benchmarks. Wasm IMHO is a smaller step forward, but I think the mapping is direct enough that a polyfill lib can handle deserializing wasm to asm.js - not ideal, but at that point it's unkillable again. Very different from {P}NaCl, which was very successfully killed by everyone except Chrome ignoring it.
DISCLAIMER: I've read about these techs but haven't had a chance to use them in anger yet; apply pinches of salt to taste.
I was all aboard the ES6 hype train before I realized that ES6 was one of many stops. Yes, the ES6 standard may be double the size of ES5 but most of the features were also necessary.
ES7 seems like it will be a sizable change as well, and as the author points out, JS seems to be destined to design by committee. The other aspect of this, which the author points at but never says (JS is C++ and they prefer minimalist languages), is JS is stuck with backwards compatibility issues. ES6 adds proper scoping with let but can't completely remove var due to lots of old code. How do you handle that?
You can't be too upset about asm.js becoming irrelevant because it was a rough draft of an idea and WebAssembly is an improvement on that. Better we fix those mistakes now instead of waiting 20 years to build on an already adopted but unsteady foundation (ala JS?). Despite some issues that might bother them (like feeding an AST instead of a CFG), hopefully WebA does its job well and lets us use those minimalist languages already mentioned.
This, one hundred times. The current excuse for JS's surprising behavior is legacy and the fact that it was built in ten days or something.
Now that we are not in such a hurry, could we please fix the thing? It's not like new ES6 code is backwards compatible anyway.
I'd argue that we don't need many of those features. Lua is tiny, has a tiny interpreter, has a fast compiler (LuaJIT) and has been resisting new language additions and doing fine anywhere it's deployed. It helps that it has a nice design from the start.
But it doesn't have brackets and semicolons. People just love those, it seems.
Imho, the perception of C++ as a large language comes principally from the high combinatorial complexity of its feature-set. It is very much a toolbox language. C++ advocates have only just recently started preaching a collective 'Pythonic' or 'Rubyist' way ("modern C++"). It is, however, still very much a broad church, with less philosophical baggage than many other languages. Strong and differing opinions on the committee seem to keep a single dictatorial programming style from emerging.
Tbh, I don't know what the author is worried about. Does Javascript have an overriding mindset/philosophy that is being eroded? Is that the concern? Other concerns about implementations not keeping up don't seem well-founded.
Going back to C++ / Java comparison, lets have a look at some objective and subjective metrics. I am analyzing "The Java Language Specification - Java SE 8 Edition" and "Working Draft, Standard for Programming Language C++ N4527", in case someone would like to repeat this exercise.
The Java specification has 780 pages, C++ standard has 1367 pages. Of course there are quite a few objections to be made about this comparison. First, if you open both standards side by side it is quite clear that typesetting and margins are quite different. Java has wider margins and a bigger font. So as a next step lets have a look at number of words. I converted both PDFs to text using pdftotext and counted number of words using 'wc -w'. This gives 227958 words for Java specification, and 477719 words for C++ standard.
But that is still hardly fair. C++ standard contains description of standard library, Java specification in general does not (partially it does specify Object, Class, Thread, and some of exceptions, but lets ignore this issue). How many pages of C++ standard constitute description of standard library? I would say that all from "17. Library Introduction" up to "30. Thread support library", additionally including "Index of library names". Those constitute 777 pages, leaving only 590 for description of C++ language itself. That would be less than Java specification, but if we go back to word metric, this gives us 249186 words for C++ standard, a little bit more than Java, but not much.
From more subjective perspective, I would say that Java specification is written using much simpler language, but that does mean that it is less precise. Moreover it seems to me that Java specification contains more non-normative text than C++ standard does. I would also say that reading Java standard from front to back doesn't seem to be very challenging (with small exceptions like overloading, which seems to be one of most complex parts of Java). And when I write 'reading', what I am really mean is reading and understanding. On the other hand I would never said similar thing about C++ standard. Understanding C++ just by reading standard seems almost impossible, as most of commentary and useful discussion is contained elsewhere: in proposals and defect reports.
Hey, how about that, another person who thinks this. And this from someone who read the entire ES5 specification and built a JIT compiler for JS. She gives a good example of the web moving too fast. Already asm.js is obsolete and it didn't even mature enough to be used. It's starting to feel like complexity for complexity's sake.
Java and JavaScript both had a chance to win in the early days of the browser wars. JS came out on top, and it was vastly simpler than Java. Now they want to turn JS into Java. Maybe this will be the opening Google's Dart needed to take off.
Also, this evolution should not be too disruptive. First, asm.js content will continue to work, since it is just JS; it will also continue to be fast (in fact, WebAssembly will polyfill into asm.js in the short term). Second, tools like Emscripten will be able to emit both asm.js and WebAssembly, so that those users don't need to even care about what their compiler is producing (and those users are the great majority of people using asm.js on the web).
The problem is around the API. I know you do your best to provide a platform similar to native (with fopen(), sockets, SDL...) but I wonder if it is not simpler to do that with a VM (a kind of kernel for emscripten) ?
From time to time, I look at qemu source code to find a solution. Originally, Fabrice Bellard did a standalone libqemu but it was removed. There is the SPLICE protocol too for the graphics or even VNC.
I'm thinking of a layer that do not rely on the DOM or emscripten JS pragmas. Thus we could have a world of lightweight linux/bsd distros for the web.
PS: I've seen your work on musl and signals.
WebAssembly will have the same API access as asm.js, both can call into JS (and JS can then access any web API).
I think of something more low level for a VM that could run inside a web worker (or in the main thread).
It's visible interface could be (with ArrayBuffer):
- an address space for a virtual framebuffer
- an address space for a virtual disk
- i/o with ports for sockets, mouse, keyboard ...
With that, we could use existing OS. There is too much case to implement all the existing API and each case can be complicated and have implicit assumptions.
For example, instead of mapping fopen() paths to localStorage or URLs in XHR, we could implement an existing hadware API for disk storage.
Instead of implementing SDL, implement a VGA memory.
I think it is more reliable to use on the lowest interface and you can reuse all the stack (from the kernel, to GNOME and Firefox, all inside the browser).
The rules of mapping what to what will be defined outside the VM. The browser could be in charge of these rules.
The rules are:
- save this address space to localStorage (or IndexDB)
- send this address space in XHR (or websocket)
- put this address space to this canvas (with putImageData())
I had this idea after reading a spec of a VM for a Forth:
http://retroforth.org/docs/The_Ngaro_Virtual_Machine.html#i-...
I'm not criticizing your work nor emscripten at all. I'm a big fan :-)
It's more about making the things simpler, get rid of the complexity, increase the features and liberate everybody of the burden of mapping native API to Web API. It's like Cygwin vs qemu/kvm.
I'd like to help emscripten and I see that.
In general the web is actually going in that direction, for example WebGL is similar to low-level OpenGL. But obviously in many other APIs, that is not the case.
There are proposals for various new APIs, like for file storage, but they are each being debated separately. I don't think WebAssembly is going to change anything in that regard - we can propose new APIs for it, but the proposals will go through the usual processes.
Ideally, qemu could run a virtual cpu just made for asm.js or wasm. The virtual hardware is accessed thru the Module functions. We could have a peek() and a poke() like in the old days to read the ports :-)
I remember your first posts about emscripten and the first script in Python. The gap to fill is similar to "write a backend for LLVM" as you did (not enough, of course).
There is also the x86 emulator from copy.sh (http://copy.sh/v86/).
The general direction is "support blobs in the browser".
About implementing new Web API, I think the process is not so slow but it relies on non-technical things (like strategy for the companies) so low level would speed up that.
After reading hundreds of blogs and articles about this or that programming language being supposedly "simple", sentences like the above have come to mean nothing.
I wish a had a succinct meme to describe what actually happens in the real world around "simple" languages but the concepts are:
If there's a "small" or "simple" FORMAL language specification, it means there's a "large" INFORMAL language out in the wild. The "informal" will include things like idioms, patterns, macros, code generators, industry practices, "utility" javascript libraries, etc.
For example, take the concept of "classes" that supposedly nobody needs in Javscript (because protoype chains are superior). What is the longest most complicated chapter of Nicholas Zaka's Javscript books[1]?! It's the long chapter on manually simulating classes using prototypes! Same situation with other books that describe home-grown "modules". Even if one chooses to avoid simulated classes in his own js code, one still has to understand the different variations that others write. If classes are not formally specified in the language spec, it's informally specified in everyone else's books, stackoverflow answers, blog articles, and youtube videos explaining js simulated classes. If Javascript had "classes" earlier than ES6, perhaps the over abundance of informal adhoc "class objects" would have been completely avoided.
Another example would be "optional default" function parameters. Since javascript's formal language spec doesn't have a feature for default params, it is "simpler" and "easier to learn". (Hey, if one doesn't have to memorize the keyword "optional", that's one less thing to worry about, right?) Hmmm... really?! Look again more closely.[2] The "optional" feature is simply moved into an idiom (multiple idioms!) that all competent javascript programmers must learn. The "smaller" language hasn't saved any complexity -- it does the opposite -- it made JS usage more complex overall.
Any language that's used for non-trivial purposes will not be "simple" if looked at holistically by combining both the formal and informal real-world uses of it.
However, within that unavoidable complexity, there can be limited subset cases of "simple" for certain scenarios. What does one want a "simple" Javascript language spec for and what can it do? Make the monkey dance?[3] Ok, that's one mapping of "simple" to an end goal and 1995 Javascript specification is probably enough. However, people want to do much more complex apps with Javascript without having to mess around with Typescript, Babel transpiler, etc.
To blog writers: please stop characterizing languages as "simple" without any qualifications of use cases. That adjective is no longer convincing on its own.
[1]http://www.amazon.com/Professional-JavaScript-Developers-Nic...
[2]http://stackoverflow.com/questions/148901/is-there-a-better-...
This is exactly right, pushing language features into user-land just leads to a load of competing equivalent solutions that developers must learn. The language is simpler but it becomes harder to actually use.
To write proofs? You don't need to worry about the larger idiom of how the language is used for that.
And to write a correct implementation of a language you don't need anything except a correct simple spec. To perform well for idiomatic code you may need to know about idiom.
To enforce idioms you include them in the language. This makes the language easier but less simple. It also means people will use exactly one idiom instead of lots of variants. This improves performance and makes it more predictable.
To perform well for idiomatic code you must know about idiom and have consensus about it and teach it to everybody.
But there's another side to it: JS is essentially a language to write code to be run on a foreign machine with quite a vague permission to do so. There's an interest in understanding what some piece of code is actually doing, in order to evaluate, whether the permission should actually be granted or not. (E.g., I might prefer not to use a WebApp, if I find me tracked in a way that doesn't conclude with the nature and value of the service. Even, if a free service, the price might be too high. Or, I could find me integrated into some kind of ad-hoc P2P network [WebRTC] that is far exceeding my planned investment in resources and which's use might not converge with my intentions.) The actual chance of doing so correlates with the learning curve of the language used. IMHO this is quite a strong argument for using a language that is both high level (as opposed to Emscripten + ASM) and of a quite scarce formal definition.
The whole talk is expressed in terms of words of one syllable.
Instead, his main point is that a successful language can start small and it is inevitable[1] that it will grow into a larger one. Therefore, let's plan on its growth from user feedback. To help the thinking, he defines a sort of "meta framework" for the directions a language can grow. The idea is that the growth can be more systematic instead of a random chaos of adding keywords and syntax (e.g. PHP).
My message is orthogonal from Steele's. I'm saying that evangelizing that a "language X is simple" in terms of a formal language spec is not useful to real-world programmers. The working programmers actually care about holistic simplicity/complexity that combines Formal specs and Informal idioms.
[1](my description not his because he used 1-syllable words)
"There are only two kinds of languages: the ones people complain about and the ones nobody uses" - Bjarne Stroustrup
Source - http://www.stroustrup.com/bs_faq.html#really-say-that
Citation needed.
Python is a popular first / teaching language and it has as many (and probably much more in 3.5) features as JS.
And Scheme is supposedly simple, but not that popular with any large amounts of people, beginners included.
There are features that interact in mysterious ways and can be difficult to master (C++ has a lot), and features that are mostly orthogonal (e.g. template strings don't complicate anything related to arrow functions and vice versa).
What I'd like to see, with regards to Javascript, is for "strict mode" to extend to the correction of old, long standing warts (e.g. crazy coercion rules etc). But I guess with this new shared "bytecode" for the web announced, we probably wont have this problem for long.
Or rather, you can still have "personal opinions" but without arguments backing them are of no use to anybody and you might as well not state them.
> Citation needed
Uh huh.
Obviously yes, I do think it, and I gave an example.
Or rather, I think that number of language features is not related to how easy it is to teach, debug, optimize and understand.
Python has tons of features (maybe even more than ES7 for which he laments) and yet it's an easy to teach and understand language.
And inversely, C is succint and has few features, but it's complex to teach and debug.
One key insight it: a language might be big, but you don't need to use all of its features (or even teach them all).
You can start someone with basic Python, for example, without delving into async or metaclasses and he can still do tons of stuff. Contrast with the "simpler" and much smaller C, in which he needs to understand pointers (a tricky subject) in order to even use the standard library.
A second insight is: a language might be big, but its features could be orthogonal and easy to understand in isolation, not the "features subtly affecting each other" mess C++ is.
Instead of letting developers code in a sensible language and simply making JS a better compiler target, the language was bloated with cruft to support manually writing it. For a notoriously overburdened language like JS this is definitely the wrong direction. Like with C++, you now have to judiciously choose which features of the behemoth to abuse and woe betide you if you choose unwisely.
Don't touch JS with a ten-foot pole, let a compiler do this dirty work for you.
Do you think maybe the push for the extra functionality is an effort to standardize the millions of JS libraries out there that do this "high-level" functionality already, rather than leaving it up to the user for interpretation?
Look at even a modest node.js project, and dig into your node_modules tree, it's amazing how many different modules wind up in your codebase to do the exact same thing(s). Ramda, lodash, underscore all in there, and hopefully not all leaking into your client-side.
Hell, I'm working on a project now that has both jQueryUI and Bootstrap components in play... and a dozen or so extensions/modules for each of them.... It's pretty ugly pretty quickly. And I don't think the likes of Component or Polymer are all that better in practice. The more that starts to be in the box, and the better people understand it the better in a lot of ways.
Who cares!? You don't have to use every feature of a language.
On the other hand:
What do you expect when something is designed by committee? Everyone wants to add their own special sauce to the mix.
Someone claiming to never be mystified by an obscure incantation of c++ either is lying or hasn't looked very much. I suppose something had to be invented to make bad perl look crystal clear. Insert bad joke here about not needing a contest to have a obfuscated c++ competition.
She picked her favourite companies, I guess :). The reality:
"The team working on WebAssembly includes people from Mozilla, Google, Microsoft, and Apple" https://en.wikipedia.org/wiki/WebAssembly
It started with explaing all the ugly part of the DOM: Variables that are constant, variable that are more like setters, variables that don't show up in a for(x in y) loop.
I was very exited. Are they goning to fix all this ugliness? Tidy up that crap?
NO! They said: "We want to be able to implement the DOM in JS. That's why we are going to add all this crap into JS". I have no idea from what perspective this makes sense. It's not just that I think it's a bad idea, I have no clue how anybody else could come to the conclusion it was a good idea. This was a way worse than C++. But I think in the end it didn't happen.
"At first glance I thought meant it was the C++ of the web by popularity"
Someone should introduce this dude to the novel concepts of "figures of speech" and "metaphors" as he's completely clueless losing the plot.