See also: how perl8.com used to redirect to scala.com
JavaScript isn't Scheme, but it's close enough for most programmers working in the real world. (There's even a JavaScript version of SICP.) And while Hackernews rubs one out to Lisp Machine porn, our computers are slowly turning into JavaScript Machines.
But ultimately, closures, first-class functions, and lexical scope are all anybody really cares about. The bits that set Scheme apart are tail-call optimization, hygienic macros, and first-class continuations.
* Tail-call optimization fucks with your ability to have correct stack traces when an exception is thrown. You know, exceptions -- those things the Scheme implementor community didn't give much thought to until R6RS. Anyways, not having correct stack traces is a HUGE no-no in production code, which is why the JVM doesn't do TCO and never will.
* Hygienic macros -- Common Lispers are snickering right now. As the article said, syntax-rules is tricky enough to implement without all the added shit syntax-case adds. They both are much more difficult to use than CL's DEFMACRO, and for what? To prevent a class of beginner-tier mistakes that are easily worked around with gensyms. And anyway, JavaScript programmers are one 'npm install' away from Babel or any number of other frameworks that parse, emit, or transform JavaScript ASTs, so so much for Lisp's killer feature in general.
* Continuations -- you're fucking kidding me, right? Continuations are to programs what time travel is to stories: the implications of adding them will blow your brain, so if you're smart you won't use them.
I think that’s misleading.
Not having a comprehensive stack trace is much more painful for imperative or especially OO code, where the state at the time of failure is practically impossible to discern.
Erlang gets away with it (for decidedly non-trivial production code like much of the world’s cellular routing) because state is much easier to determine.
(Or maybe I’m blowing smoke. Certainly that’s how it feels to me.)
Safari/JScore, the only browser to implement TCO solved this using shadow stacks.
TCO -> I see your point about stack tracing and tend to agree, but more importantly, one key difference between Javascript and Scheme is the focus on recursion. Javascript decided that imperative looping was the proper, idiomatic way to handle iterative expression construction. With this design decision, leaving aside whether the looping vs recursion is an equal trade, TCO was not going to be a priority and the style of programming grew around that first choice or iterative style.
Hygienic Macros - I love macros. However, in contrast to your position, I like my macros like I like my martinis... clean, as a general rule. So while I like a basic assumption of hygienic macros I also want the capability to produce ugly dirty procedural macros to be available. But that is just a preference of mine. I agree that the wealth of options for automated and principled syntax tree manipulation and code generation makes the need for built in macros almost non-existent.
Continuations -> while I understand the strong warning, drifted continuations enable some very nice coding possibilities, particularly implementations of generators, coroutines generally, and better callback syntax. Javascript just decided that instead of handing devs the keys to the Delorean they would just chauffeur everyone, i.e. they built constructs for these common and useful patterns directly into the language semantics. This is particularly the case for future based coroutines, now with the async/await sugar.
I have debugged poorly written defmacros for longer time than I spent fighting macro hygiene. I implemented defmacro using syntax rules (about 7 lines of code if you have access to schemes with optional and keyword arguments) and use it frequently. My rule is however that if I ever want to introduce bindings of any kind I will use defmacro. Simple. Saves me a lot of pain. But when it comes to macros there is no truth. This discussion has been going on long enough for most o us to know that it is a matter of taste.
Call/cc is overkill. It is a shitty, leaky abstraction that nobody really wants. Delimited continuations are the bee's knees! They compose, capture just the things you tell it to and are fast. They follow the idea of having a well chosen set of primitives as building blocks. You want CL's tagbody? No problem. Fast coroutine style generators? You got it. Cooperative, fiber based multitasking? Just a pure scheme library waiting to be used!
[...]
>In some weird organic process, the pantheon of programming languages have ordered themselves in terms of prestige. It’s as random but undeniable as music and fashion. Radiohead is on one end, and Nickelback is on the other. No one knows precisely how they got there, but there they are.
>On the Radiohead end, you’ve got Common Lisp, Scheme, Smalltalk, and a few others. Scheme is even more Lisp than Lisp, so it’s like that weird avant garde band no one’s heard of that Radiohead always claims inspired their latest album. If Lisp is Radiohead, Scheme is Kraftwerk.
https://journal.stuffwithstuff.com/2013/07/18/javascript-isn...
My friends, coming from hopelessly mutable languages like python, could hardly get any work done at all.
This was back in late 2017, and things might have gotten better since.
I remember at first no one took js seriously. It was only after people started to realize that web pages were an incredibly compelling app-platform that that befan to change.
So I think if Brendan had gone with Scheme, Scheme would be taking over the world like js is now.
Basically, platforms make languages popular, not the other way around.
Yeah, a Buick is like a Toyota. Both can get you where you want to go. But close enough?
That's gross. Please don't do that here.