> Javascript... what an odd choice. Definitely not my first choice for a language used to teach programming to beginners, nor to run on embedded systems.
The problem is that you are looking through a lens of Javascript in 2014 where it has become a bloated pig of a language.
Javascript in 1996 when it was introduced ran on a system that was roughly 66MHz, 64MB of RAM, 10's of GB of disk, and 56Kbps of bandwidth. And, it ran as a subsystem inside the Netscape process, so it probably had access to less than 2MB of RAM. Microchip just released a PIC32 (MIPS R4K) with 200MHz, 512K RAM, and 2MB flash. That's a pretty good match in terms of capabilities.
Javascript, the language of 1996, is actually pretty decent and is a small language.
Let's look at the alternatives:
Scheme/Lisp fails for a variety of reasons but the biggest one is that a cons-cell is a terrible abstraction on modern hardware (see Clojure for a Lisp with good modern abstractions).
Lua is a 1-based language in a world of 0. Sorry Lua, but that's just not acceptable. Every time you cross the Lua-C boundary, bugs abound (well, they abound in Lua, too, but I'm being nice).
Forth is stack-based in a world of imperative, register-based abstractions.
So, what's left? C. Which takes almost 18 months to train a new junior programmer in until he's useful at embedded programming. It takes about 6 months to beat C pointer manipulations into his head, and then another 12 months to beat all of the coding conventions into his head so that he doesn't blow off his foot.
God, I hope Rust gets it right. Please. We really need a compiled systems-programming language that works in a world of concurrency.
Now, let's look at Javascript.
Failures:
lack of direct hardware accessors--every Javascript will have to grow some way to read/write pointers/memory in embedded. Yeah, that's a big one, but not that huge.
function scoping--Correctable with the "let" keyword--just don't teach "var".
inheritance--Better to have left it out that to have done the bodge that is the Javascript implementation of prototypal. Prototypal inheritance is fine, but the way Javascript implements it is terribly broken.
mutable system globals--sigh. Yeah, it's enabled beautiful things like installing workaround for broken Javscript interpreters, but it also means there is almost nothing you can count on.
So, if you sit and think a while, Javascript is actually pretty good for an embedded language. It's at the 80% point at least. It's probably closer to 90% (once you add a hardware accessors).
The real question to ask is: what should an ideal embedded language look like? Small (check--only Forth is smaller). Brace syntax (check). Vectors, Hash Tables, Garbage Collection (check). Concurrency (fail-but nobody else gets it right yet either). Interpretable or compilable (check). Widely known (oh, yeah).
Javascript fits the hole. Yeah, it's not what I would have expected, but if you look at it clearly, the evidence checks out.
> cons-cell is a terrible abstraction on
modern hardware
Could you expand on this?
Also, whether or not it's better to teach to kids than JavaScript, Squirrel is a more traditional curly-brace alternative to Lua for embedded development.
> > cons-cell is a terrible abstraction on modern hardware
> Could you expand on this?
Sure, that one is pretty easy. cons cells are effectively 2 pointers. Consequently, they are not guaranteed nor expected to be near one another in memory.
Now, that's not a big deal with respect to the first pointer. That contains the thing, so we always have to chase that down.
In a Lisp/Scheme cons-cell list, the second pointer needs to be referenced to get to the next cons cell. So, we have to chase a second pointer just to move to the next element.
Every time you chase a non-contiguous pointer like this, the processor may have to bring in a cache line and that's a big penalty.
Contrast this to say, an array/vector. To get to the next element you just add some small amount to the current index. It's likely already in the same cache line as the previous element.
Arrays/vectors have a big win over pointer-based lists in terms of locality of reference on a modern microprocessor.
There is a second problem with cons cells in that their abstraction in terms of the language also has problems:
What is so much better between Squirrel and Javascript? To my eye, they look pretty much the same.
And Javascript has an enormous ecosystem. While Squirrel has a very small niche of the not terribly large Lua ecosystem.
This isn't to knock Squirrel as a language, but I view this in the same light and Python vs. Ruby. The languages don't have enough better/different from one another for me to tell someone to switch if they already know one or the other.
The problem is that you are looking through a lens of Javascript in 2014 where it has become a bloated pig of a language.
Javascript in 1996 when it was introduced ran on a system that was roughly 66MHz, 64MB of RAM, 10's of GB of disk, and 56Kbps of bandwidth. And, it ran as a subsystem inside the Netscape process, so it probably had access to less than 2MB of RAM. Microchip just released a PIC32 (MIPS R4K) with 200MHz, 512K RAM, and 2MB flash. That's a pretty good match in terms of capabilities.
Javascript, the language of 1996, is actually pretty decent and is a small language.
Let's look at the alternatives:
Scheme/Lisp fails for a variety of reasons but the biggest one is that a cons-cell is a terrible abstraction on modern hardware (see Clojure for a Lisp with good modern abstractions).
Lua is a 1-based language in a world of 0. Sorry Lua, but that's just not acceptable. Every time you cross the Lua-C boundary, bugs abound (well, they abound in Lua, too, but I'm being nice).
Forth is stack-based in a world of imperative, register-based abstractions.
So, what's left? C. Which takes almost 18 months to train a new junior programmer in until he's useful at embedded programming. It takes about 6 months to beat C pointer manipulations into his head, and then another 12 months to beat all of the coding conventions into his head so that he doesn't blow off his foot.
God, I hope Rust gets it right. Please. We really need a compiled systems-programming language that works in a world of concurrency.
Now, let's look at Javascript.
Failures:
lack of direct hardware accessors--every Javascript will have to grow some way to read/write pointers/memory in embedded. Yeah, that's a big one, but not that huge.
function scoping--Correctable with the "let" keyword--just don't teach "var".
inheritance--Better to have left it out that to have done the bodge that is the Javascript implementation of prototypal. Prototypal inheritance is fine, but the way Javascript implements it is terribly broken.
mutable system globals--sigh. Yeah, it's enabled beautiful things like installing workaround for broken Javscript interpreters, but it also means there is almost nothing you can count on.
So, if you sit and think a while, Javascript is actually pretty good for an embedded language. It's at the 80% point at least. It's probably closer to 90% (once you add a hardware accessors).
The real question to ask is: what should an ideal embedded language look like? Small (check--only Forth is smaller). Brace syntax (check). Vectors, Hash Tables, Garbage Collection (check). Concurrency (fail-but nobody else gets it right yet either). Interpretable or compilable (check). Widely known (oh, yeah).
Javascript fits the hole. Yeah, it's not what I would have expected, but if you look at it clearly, the evidence checks out.