What an interesting and ambitious project! Of course the first thing I did was skim the Metacircular Interpreter section to see how they handled the additional syntactic complexity. They gloss over the "parse" function, which is probably the best one can do. That the Scheme function "read" could be implemented by a novice is one of the advantages of using Scheme for SICP and it wouldn't be reasonable to expect an adaptation like this to reproduce the exact experience. I do think it's great the way SICP leads people through doing powerful things with a programming language, and then shows them that they themselves could implement the language they've been using. It gives a powerful feeling of control in an environment (computer programming) that can otherwise be intimidating. I think this adaptation does almost the same thing.
The translation is pretty direct, so the data structures are more idiomatic to Scheme than they are to JavaScript. I think that's OK.
> The translation is pretty direct, so the data structures are more idiomatic to Scheme than they are to JavaScript. I think that's OK.
I do wonder if it wouldn't be simpler to write a Scheme interpreter in JS (or take one of the undoubtedly existing ones) and make the book interactive with that.
This version feels more like something that has added value if you already know JS, not so much when you're learning JS
> This version feels more like something that has added value if you already know JS, not so much when you're learning JS
Totally agreed, which I think is a strength of SICP. I know historically it was for learning computer science, but I've gotten so much out of reading it, despite not being a newcomer to the field.
Of course SICP is brilliant in Scheme. But hello? There is no such thing as a “blub language.” Your comment misrepresents the entire point of the original PG essay!
The point is that givens some fictional language called “Blub” for the sake of the essay, some programmers believe that their language has everything that could possibly be useful, productive, expressive, &c.
But PG’s contention that languages exist on a continuum of power (a gross oversimplification), and when a programmer believes that their “Blub” is as powerful as possible, they have closed their mind to more powerful/useful/expressive ideas.
But that’s as true of Scheme as it is of JS: If someone believes that LISP was the zenith of programming, and everything else since then has just been wankery, if they think we have nothing to learn from Haskell, or Julia, or Joy... Then for them, Scheme is Blub.
Blub is a mindset, not a language. Sure, some communities might be infested with Blub programmers, but nevertheless, languages themselves are not Blub.
Now, if someone says that SICP in JS proves that Scheme is no better than JS, well... That person has a Blub mindset. But teaching some of the same principles as SICP using JS is not in and of itself the Blub mindset.
Summary:
Blub is a mindset, not a language.
All languages are Blub languages if someone has the Blub mindset.
Considering everything is being shoved into the web paradigm and written in JS even when it's wildly wrong for the job, I think it fits the description perfectly.
If you really want a blog post to describe how JavaScript is eating the world, I suggest it isn’t “Beating the Averages” by Paul Graham.
It’s actually “Worse is Better” by Richard Gabriel. I don’t think people are writing JavaScript tooling while saying that JS is just as powerful as Haskell or Lisp. What they’re saying is that its ubiquity is valuable and for their use case, ubiquity and network effects trump productivity and/or “power” however we might want to define them.
"Do you know enough lisp to write a self hosting interpreter in it?"
Short answer: Yes.
Long answer: No!
I learned Lisp and TI-Scheme in the early 80s, and somewhere around then we did some SICP-like stuff in undergrad CS.
I later came upon SICP and worked my way through it, having the usual "Aha!" moments. I thought I knew something about Lisp and Scheme at that point. I built some self-hosted interpreters using the following pattern:
1. Write an interpreter for a minimal subset of Scheme in a host language.
2. Write an interpreter for a more full-featured Scheme in the subset of Scheme.
At some point, I read LiSP [0], and I discovered that what I thought was enlightenment was actually but a hint of the delights to come. The entire book is about teaching programming through the device of building interpreters and compilers.
So my next pattern was something like:
1. Write a minimal Scheme interpreter in a host language.
2. Write a Scheme compiler in Scheme.
3. Bootstrap the compiler by running in in the interpreted Scheme.
4. Now you have a compiled Scheme implementation written in Scheme.
5. Build out more features.
And now, this approach is one of my go-to tools. A few years ago, I was playing with Turing Machines, and I used a "constructive proof" approach: If we want to demonstrate that a Turing machine with tape that has one end is just as powerful as a Turing Machine with a tape that stretches to infinity in both directions, write a compiler from one kind of Turing Machine to the other. And so on and so forth to prove that being able to write an infinite number of different symbols is no more powerful than writing 0s and 1s. Or that a multi-dimensional Langdon's Ant is no more powerful than a Turing Machine...
Interpreters and Compilers are very powerful tools for constructive reasoning.
But the point of the discussion around Scheme for this purpose is how easy it makes writing Interpreters and Compilers. On the one hand... Shrug... Since we can write interpreters and compilers in any language.
On the other hand, a tool that removes a lot of the accidental complexity in writing interpreters and compilers changes the way we think about writing interpreters and compilers, much as parsing text using a language built around pattern matching (like SNOBOL and its descendants) changes the way we think about parsing text.
So... We are probably in deep agreement about the value of SICP in Scheme, and the value of Lisp in general, not just as a language, but as a way of changing the way we approach solving problems.
And as for knowing enough... The truth is, every time I sit down with certain programming ideas, I learn more and realize that what I thought I knew was incomplete.
So in a very real sense, I suspect that no, I don't know nearly as much as I think I know.
Thank you for writing this up Reginald. I appreciate seeing the journey that someone such as yourself has taken in learning these ideas, and the perspective that it has imparted along the way.
"When we admit we know nothing, then we are free to think anything."
As a C developer: while I could probably do that given a few months, I've somehow managed 25 years without needing to interpret C? It's cool and all, but in terms of product requirements tends not to be high on the list?
Most languages are vulnerable to contexts where their particular gimmick doesn't work. You probably wouldn't write an interrupt handler in Lisp. You wouldn't write a bootloader in it either (although you might choose Forth, the other fanatic minimalist language). Conversely C gives you no runtime dynamism. Endless people try to write language-to-Verilog converters and are disappointed.
I have written interpreters in python and god help me lex and yacc. The point is that writing one in scheme is so easy you almost think that the language was designed with that in mind, it was in case the sarcasm doesn't get through the text.
Can lisps place arbitrary code in types and formally verify complex properties of stateful systems--all in the same language? Doubt it. Lisp isn't the epitome of power.
No. You can write a compiler for any language in Scheme, but it's disingenuous to say that Scheme has that language's features. There are many languages with way more powerful features than Scheme if you're comparing type systems.
Lisp in general is not the epitome of simplicity. Lisp-2s like Common Lisp add some cognitive load for those used to simpler languages (although Lisp-2s have their advantages).
And of course, Lisps that include meta-object protocols (Flavours, Common Lisp again, &c.) deliver power, very elegantly, but for people unfamiliar with them, there is a learning curve to climb.
You're mistaking Lisp for a programming language. Which Lisp is not. Lisp is an idea (or rather a set of ideas), based on which different PLs can be implemented.
I'm perfectly aware of that. My point stands - using a concrete language to generalize over some abstract ideas might be confusing for those who are unfamiliar. In general, Lisp dialects strive for simplicity.
That is exactly the reason why Scheme was chosen for SICP.
Elegance is not always synonymous with simplicity. For example, Smalltalk’s use of Class and Metaclass is very elegant, but most programmers encountering this for the first time would not call it “simple.”
After they got over the hump and grok how the two things work together to serve as the foundation for Smalltalk’s OOP and allow programmers to alter Smalltalk’s OOP... Then the elegance emerges.
I think elegance is a measure of the simplicity of a tool relative to the complexity of the problem domain, whereas simplicity feels like a more absolute measure.
That's fine as long as we have both a canonical version written in Scheme and good "translations" to other languages---including "blub". Good translations should not diminish the value of the canonical SICP. It can be argued that this particular translation is not good; I guess not, as SICP JS's version of metacircular interpreter does interpret (a subset of) JavaScript! The cost is of course this complex definition [1] of which language metacircular interpreter is written in and implements.
Were you going to let the rest of us mere mortals in on the reason?
I think it's good to offer a version of SICP adapted to a language that's used today very prominently and is relevant to many current jobs in the industry.
A long essay could be written about that. A few quick things. There's Scheme's simple syntax, which doesn't get in the way of what the book is actually teaching. The fact that, of the mainstream programming languages, Javascript is the most crufty and full of gotchas, with all kinds of weird, unexpected behaviours even experienced developers can't always keep track of, many caused by bugs in the first version. Javascript's tendency to fail quietly when other languages would shoot out error messages makes it an awful language to experiment and play around in. Javascript Stockholm Syndrome. Decades of tradition. The entire last section of the book's intimate relationship with Scheme.
The fact that this is a book about learning to program, not about maximizing your potential for jobs. It's a compsci book to learn to be a good programmer, not a book about synergizing industry trends to build your resume.
When SICP was written, most people still wrote in Assembly for most things but COBOL, ADA, and old-school FORTRAN were also popular. Part of the longevity of the book is its appropriate choice of language.
Would it be as enlightening to write a series of JS compilers in JS? Or are they writing Lisp compilers in JS? Doesn't that miss the entire point of the book?
> Were you going to let the rest of us mere mortals in on the reason?
Scheme (in contrast to Java etc) is special because of its very
easy syntax and how it is evaluated. Since SICP is about
syntax/structure and its evaluation/interpretation you should
really stick to lisp.
> I think it's good to offer a version of SICP adapted to a
language that's used today very prominently and is relevant to
many current jobs in the industry.
I don't. Maybe this Javascript-Version is also a great book, but
if you don't know scheme/lisp and wonder why scheme is a better
choice for SICP I encourage you to read the original.
Why? Why does a textbook about fundamental principles need to be 'adapted' to technology currently in use in industry?
The Feynman Lectures uses an example of a screw jack with 10 threads per inch, and a 20" lever. Should we update this to a name brand screw jack with 8 or 16 threads per inch, and an 18" breaker bar, because those are common in industry today?
Be sure to extend the introduction of that chapter to include a history of this particular screw jack company, and who currently holds the trademark, and all the major companies that make screw jacks today, and typical uses of jacks, and how they're constructed [1].
In America, at least, that's still not what we use in industry. So the top response to my comment is a proposal to make this classic American book even less practical here!
Why does that matter? You are not going to get paid to work through the SICP exercises on a job. Rather, you are going to use the things you learned through SICP on a job. Like deciding when JavaScript is the right tool and when it isn't.
If learning a new language and syntax is a barrier, you will not be able to follow SICP anyway, since it includes developing multiple languages in various paradigms.
Come on, I'm not putting anybody down. Just pointing out that you cannot avoid learning new languages anyway, since the exercises in the book requires you to design multiple different languages. It is basically a book about language design.
I don't know anyone who first read this book outside of college. Its concepts aren't exactly directly applicable to typical work. If you're given the task to build something in Javascript for work, it's probably not a metacircular evaluator or a register machine simulator, or even a closure-based object system.
I'm curious who's reading SICP who finds it difficult to grok in Scheme, or more useful in Javascript. What are you doing in the industry that familiar syntax is top priority?
I would think that other books, specific to Javascript, would be a much better fit for people writing pretty much anything in Javascript.
That might change now. Someone might pick this up after completing a few JavaScript chapters in a JS specific book. I haven't read the book yet so I can't comment on the concepts, but based on your list it's a great resource for any newbie programmer, especially to those who are self taught like me.
> What are you doing in the industry that familiar syntax is top priority?
The question is more like: "Do I want to invest time into learning a new language just to read and comprehend new and interesting concepts?".
With endless knowledge out there, I usually gravitate towards the least friction.
> I would think that other books, specific to Javascript, would be a much better fit for people writing pretty much anything in Javascript.
I don't think of this book as the ultimate JavaScript book. It just uses it as the most accessible language out there, and that matters a lot imho.
It is a great book for self-taught programmers. But the book is about programming language concepts and paradigms, and explores these though the development of multiple languages, interpreters and compilers. It is fundamental to the book that you have to learn a bunch of small languages. Scheme just makes it really easy to implement new languages.
SICP is about exploring various programming concepts and paradigms like functional, object-oriented, constraint-based, lazy evaluation and so on. Scheme happens to be the perfect vehicle for this, since its support for code-as-data makes it much easier to implement new sub-languages and evaluation forms.
SICP is not about learning any particular language, it is about learning concepts which will make you understand JavaScript much better than anyone who only knows JavaScript.
If having to learn a new language like Scheme is an impediment to starting SICP, then you will not get past the first chapter anyway.
I'm just imagining someone taking the text of Crockford's talks on Javascript, removing all his clear description of the language features, and replacing it with highly opinionated non-technical terms of derision like this.
Though not instructive, it would be really fun to read.
If you’ve read SICP and saw how the abstractions were slowly layered on top of each other which scheme is amazing for with its simplicity - no I don’t think a weird prototypal language like JS is sufficiently like scheme enough to communicate the beauty of programming like SICP does.
“Don’t tell me it’s got lexical scope, because JavaScript’s scoping is an abomination in the face of God. Guy Steele isn’t even dead and JS scope makes him pre-emptively roll in his not-yet-occupied grave. Likewise, claiming JS is homoiconic because you can eval strings of code is nonsense. If that’s the only criteria for homoiconicity, then C is too, since you can treat an array of bytes as code and jump to it.”
It's a wonderful read, but having used JS since well before it attained its current status as a combination floor wax and dessert topping...
The scoping for "JavaScript, The Good Parts" is exactly the same scoping as Scheme. You can write expressive programs without ever using var, let, or const just using binding to named function arguments, which is very close to thinking in lambdas.
Of course, that style of JavaScript isn't what most people think of, and without macros, you can't build fuller-featured syntax on top of "The Good Parts."
And that's the real problem with treating JS as "a kind of Lisp." It's true that you can program in a certain minimal SICP-like style in JS, but if you have to write a Babel plugin to implement a new feature made out of closures and argument bindings... Then you really aren't programming in "a kind of Lisp" any more.
"to be fair, it does have some stuff in common. So maybe it’s a fair comparison? I guess the real way to tell would be to compare Scheme to some other languages. The big feature that everyone harps on is closures. Maybe just having closures means you’re basically Scheme.
If that’s true, then C#, Lua, D, Erlang, Haskell, PHP, Scala, Go, Objective-C, Python, Ruby, and Smalltalk are basically Scheme. In other words, if JavaScript is Scheme by that criteria, then every language is Scheme, which of course means none of them are."
"This is why the “JS = Scheme” meme drives me crazy: it makes us dumber. It’s a thought-terminating cliché. It carries negative informational content and makes people actually know less about languages than they did before."
Hey, I'm not claiming that JS is Scheme, or that Scheme is defined by closures :-)
My personal "What makes Scheme, Scheme" predates current Scheme implementations by decades. But I go with, "There are five special forms that are essentially axioms of the language, and everything else is made by combining those forms with each other."
The deep elegance of building a rich language on top of a handful of axiomatic features is what makes Scheme feel Scheme-ish to me.
I understand that Scheme has evolved since everything was implemented in terms of the special forms, but still...
This rebuttal isn't worth much, as it was written back when js was a much different language, some 2 years before let/const, promises and probably half of what modern js developers use day-to-day. It is also way too snarky to take it seriously. Not gonna lie, it was a fun read though.
I wasn't trying to flamewar, but my post was kind of snarky and I should have expanded upon it. It's just that when I see something like "SICP in teh script" I can't but question the value of that, since much of the elegance and staying power of SICP is inseparable from the fact that it was designed for a homoiconic language with simple syntax and easy metacircularity.
Every single language in the industrial use today is pretty much influenced by Lisp. For that reason alone every self-respected programmer should get familiar with a Lisp - Racket, Clojure, Fennel, CL, etc.
Is that sarcasm? I can't even tell any more. Assuming it's not:
Do you mean modern PHP? "The source code of the Viaweb editor was probably about 20-25% macros." So are you suggesting they should have started work by extending PHP with Lisp's macro system? Or just worked an order-of-magnitude faster to make up for not having one?
Or do you mean the actual PHP that was available when they started Viaweb? It's hard to imagine how Personal Home Page Tools 1.0 (not even called a 'programming language' at the time) would have been at all a reasonable alternative to ANSI Common Lisp. It was a few C files that could do basic variable substitution and output HTML tags to stdout. It couldn't do loops or if-statements, much less access files or databases.
Finally have a free 1 hour and try the site. The site cert. is not valid ... and also if you start with the book, click it does not result in running code. More important the first preface is about Scheme which I think it should be in reverse. My 1 hour up. May try later.
"less common" is a bit of an understatement[0]. I'd put it in the "common misspelling" category. Though both versions seem to have been around since before English really had consistent spelling.
Every now and then a great movie comes out. Then it gets its American remake. It's been proven you can put Al Pacino, Robert de Niro and Bruce Willis in any movie (with predictable results!). This is the book equivalent of an American remake for me.
Is Javascript the new pseudocode? Honestly I'd rather be forced to learn a new language to understand a book than to read the book adapted to JS.
I just wanted to take 2 minutes to thank you personally for that comment. Honestly its amazing to find another person on this planet who has the exact same reaction to this idea ! I was going to type out what you said pretty much word for word, and then I'm reading what you wrote & I'm like, hey, who's this person who has read my mind & how're they doing that ? For a minute it was like, completely mindblowing.
I think most of the comments below are entirely missing the point & thinking of this as JS hatred. Its more about...cultural degradation...Pedestrianization. sicp was holy grail. you looked up to it, you cherished it, it was something few people have partaken of & it was nice that way. then gradually that got diluted over time. berkeley did the python3 gig & that itself was icky but now this is a whole new low. sicp in js ?! jesus. what next ? are we going to sicp in qbasic ? why not a sicp do-over in Visual Basic so all them fogey 90s microsoft-for-life developers! developers! developers! on win95 code up COM DLL interpreters in Notepad++ ? where does the madness end ?
sicp & scheme. buttons & bows. mac & cheese. bread & butter. things that go together.
Now, sicp & js is...is..what is it ? mustard & jam ?
you know what would be real cool ? sicp in J !!! Now that's a marriage made in heaven. if i was a rich vc i would happily fork over a million for a sicp in J effort. the apl family has so much to offer! now that i recall, there was actually an effort called aprol http://www.cs.trinity.edu/~jhowland/aprol.paper.pdf
I think the target audience is people who don't like to learn, and I find that worrying in the context of programming.
It's not like code examples in a book are intentionally obfuscated. They are also not some atrocious pile of spaghetti code you may have to put up with at work. I think any foreign PL programming book is a joy to read next to working as a software maintainer. And while the original book aspires to be a general programming book (the title!), I think we should allow Scheme programmers to have their poster child book/success story.
I also have a modest, optimistic interest in Rust, and tinker with it from time to time, but I don't think everything should be converted to Rust. The language team is open about sacrificing readability for other values, like execution speed, memory safety, concurrency, correctness. But with Rust at least the occasional rewriting hype can be justified as "testing the limits of the new language" and "optimizing" - because the language is pretty damn efficient. With Javascript it's... what? Some kind of idealism about running all programs in a browser sandbox? And isn't it a bit ironic that an idealistic book about software architecture is rewritten in an ad-hoc language, with a minefield of bad features you're not supposed to use but you will encounter at work?
> I think the target audience is people who don't like to learn, and I find that worrying in the context of programming.
A strange comment to make about someone trying to tackle a text like this
> I also have a modest, optimistic interest in Rust, and tinker with it from time to time, but I don't think everything should be converted to Rust.
This is a great example of how your perspective differs from that of the intended audience. They don't want the book in JS because it's a language they're already picking up and want to tinker with. It's likely one of the only languages they are confident with. Maybe they just finished their CS degree or (gasp) a coding bootcamp and would like to understand more of the fundamentals before learning their second language. Especially one like LISP that represents an entirely separate branch of programming language design from JavaScript.
As someone who writes Clojure professionally, I certainly share your hope they would choose to pick up lisp eventually. Let's not hamper their development in the meantime by steering them away from resources like this that might assist their journey.
Agreed. I'm pretty sick of the anti-JS kneejerk rhetoric that happens here.
It adds zero value to any discussion. It's nothing more than a desperate attempt to gain some internet points.
It's a popular language and it has flaws, but that doesn't automatically make it worthy of the amount of hate it receives here. This type of discussion has more in common with /r/iamverysmart than it does with valuable discourse that HN used to be known for.
I do enjoy "Professor Frisby's Mostly Adequate Guide to Functional Programming", which uses JS examples extensively. Despite the fact my last job was mostly JS, I had to look up functions all the time and stretch my brain muscles. Modern JS is different than "keep it the same" JS. But... converting a book to a different programming language rubs me the wrong way. I miss an opportunity to see another language, too. It's not even some very arcane language. If it really was a knee-jerk reaction, I'd have said:
Adapting a book for another language doesn't really make you miss an opportunity, though, right? The original is still freely available for you to look at and see another language.
It's not an attempt to get internet points. It's an expression of frustration that one of the most important platforms of our time has first class support for only one language, and the only reason that language is used is because of its monopoly on the platform. Were it no for that monopoly it would rarely be used.
I'm just glad JS is as good as it is, considering it didn't have to be good. It could have been even worse and still would have succeeded due to its monopoly.
But WebAssembly was just made a new standard by W3, which, correct me if I'm wrong, will allow browsers to natively support literally any other language the developers choose.
Yes, but only if those languages do not interact with the platform (the platform being "webpages"). DOM manipulation requires JavaScript. So, it is still the case that JavaScript is the only language with first class support.
I like JavaScript despite some of its quirks and there are some annoying ones. However with the mindset to embrace JS I find it easier to work with than blindly hating it. It could be worse. You could be coding in Monkey for Garmin.
The meaning of the second paragraph was ambiguous. Aside from Javascript dislike, which I don't pretend to deny, I believe learning new things is mind-expanding.
When an intriguing movie - or book - comes out, it's often intriguing because it's quite different. When you convert it to a common language - or Hollywood - it becomes less different. Reading "Working With Legacy Code" forced me to absorb some C#, but it also allowed me an opportunity to compare it with Java, which I learned at university.
What I understand from this is that people didn't really value Python as a pseudocode language. It was just fashionable at the time. Now it's Javascript's time. I wonder what's going to be next? Golang has a chance.
I like JS. I use JS daily. JS is part of the workflow for nearly everyone I know who works with code. For me, ES6 is fantastic to use. Some of the better books on JS [I'm thinking specifically of Haverbeke's "Eloquent Javascript"] are general computing classics in their own right.
I used to be a snob about JS, due to the fact that in the 90s / early 2000s, it had major shortcomings and produced a lot of slow, crashy web pages. But when I learned modern JS, I realized that it is now a fully mature language equal to any other, and easily used in a huge variety of contexts [thanks in no small part to Node]
I have to use Javascript almost daily at work, I hate it.
Up until a year ago or so I hadn't really had to use it much, I'm finding it so bad I'm seriously looking at how I can get into an alternate career. Working with JS is a profoundly miserable experience.
Previously I was working on C# and SQL. I'm no fan of either of those, but at least with C# I can understand what the designers were thinking. Ideally I would be working in Clojure if it was up to me. Or Scala or F#.
Now it's Javascript as that is the code base our client uses. The client runs a number of production factories and have an internal web app that is mostly Javascript on the front end for monitoring these production lines.
It's made me angrily punch my desk and consider just quitting on the spot on a number of occasions.
I don't know how anyone tolerates using this day to day and doesn't want to jump off the roof. It's absolutely idiotic.
JS is a terrible language. The amount of pitfalls, language features you must avoid, and obscure paradigms you must follow to make JS usable is mind-boggling. Just because you can use JS well doesn't mean it's a good language.
While I certainly wouldn't call JS "great", I actually do genuinely like a lot of parts of it. I like the Lispey style of embedding data structures (hashmaps and arrays) directly into the language, and I like that it has somewhat popularized some functional techniques and made them mainstream.
While callbacks aren't a great way of doing continuation-passing, at least we can credit JS with making continuation-passing mainstream.
In combination with the fact that JS actually does work pretty well on both frontend and backend, it is a language I use semi-regularly for prototyping, given its flexibility. Granted, if I decide to make a "real" version of the project, I'll probably do it with a more functional language, but I think JS doesn't suck too bad.
I love it and think it's a great language. It has bad parts, but they are easy to avoid, especially with a modern linter. So there you go. You're wrong. At least one experienced developer who has coded in many languages thinks JavaScript is a great language.
Basically, you install the `typescript` package which gives you `tsc`. Then you configure Node to run your program with `tsc` through your package.json.
But I’m happy for you that you like ES6. You all own the language now, so enjoy it. Us ES5 folks are going to have to rewind and fork so we can have a community again.
I do. I love vanilla JS especially. The way it interacts with the DOM and the way JSON works makes more sense to me than most other languages, and this is coming from a python user and newly lisp user.
Not everyone has the same brain as you. People enjoy things you don't understand.
It's useful and practical and has a lot of work put into it so it can't really be called bad, but it doesn't really stack up to what native languages can provide at the high end, and never will (even if it can get pretty darn close).
Though I acknowledge its immense utility, I feel like JS always tends to go for "good enough" solutions rather than "best in class" solutions. That is its own kind of quality, but there's good reason to dislike JS for people who focus on those particular qualities in a language.
For sure, if you have a shot at making a world class system you probably don’t want JS.
But I’ve never been in a job where we had a shot at building a world class system. Maybe I just have bad luck, but at each place I have worked the problems in the codebase are obvious and the impediments are institutional not technical.
There are hundreds of problems I could list in our current codebase that are causing slowdowns, bugs, etc. None of them are because of the programming language. They are places where someone put a square peg in a round hole, where someone copied a bug over and over because they assumed the existing code was correct, where someone used a fancy feature of the programming language that made the program worse.
None of that goes away if we start using Rust.
So yes, I agree with you if you are within striking distance of making a perfect application use a nearly perfect language.
I’ve just never been in that job. I’ve always been in the “let’s fix some of this low hanging fruit, and make sensible use of the tools we have” job.
The problem is that if the system was world class then it might actually be ok if it was in js. Most codebases are a bit of a mess, like you say, and js just makes it much harder to figure out what is going on. It's not just a dynamic language, it seems to encourage a gratuitously dynamic style. So you have to figure out everything in the debugger. That is if you can even determine where to set a breakpoint!
Yeah, I actually agree with you especially for ES6. Because it requires you to transpile, and because promises/async/await break the control flow model, it is extremely difficult, often impossible to place breakpoints. With await in particular, you can forget to await a promise and then your app just stops working, mysteriously, and there’s no way to find out what’s happening except to one by one disable parts of the app until the situation becomes clear.
Transpilation as a norm means it’s kind of 50/50 whether the source code you encounter while debugging will even be readable.
Actually what I see most often, professionally, is that JavaScript developers stop believing they can inspect their application at all, and when something is wrong immediately just try to guess what’s happening. Then see if their imagined fix helps, if not try again. Basically guess and check. Which is a fine technique but it’s pretty bad if that’s your only way to debug problems.
I am able to code in ES5 sometimes on independent projects (without Webpack) and it’s a joy. The debugger works everywhere, in a consistent way. I have callbacks everywhere so asynchronous code is simple to trace and easy to understand. It’s great.
I am working slowly towards a fork of NPM/Node ecosystem that starts over before ES6. I think early JavaScript is actually a wonderful, fast, elegant language.
I would say that ES6 is so bad in terms of debuggability that you almost have to use TypeScript to make coding in ES6 bearable.
The other aspect of what you’re saying: that you have no static analysis tools so you HAVE to debug, is spot on. I think to build a great JS application you have to put an equal amount of effort into designing the test harness. Basically all the time you would have spent wrangling the type system you have to put into the tests.
And you can’t just half- ass the tests. They need to really accurately mirror your business needs, and really model the relationship between your app and your tests, in order to provide an equivalent static analysis value to what a type system would give you.
However one final point, which is that the fact that ES5 is so impoverished in terms of control flow and data modeling, I think actually helps solve all of these problems. If you limit yourselves to basically just functions and literals, you are forced to write really strong clean interfaces. I find myself being able to focus almost entirely on separation of concerns. Because I’m not dealing with fancy language features, and because I literally can’t afford to build giant complex modules and applications, it forces me to build small, simple modules that have very clear responsibilities.
That might seem like a limitation to many, but I actually find it helps me to avoid headaches before they happen.
Do you find yourself accidentally doing that often? A few of the things from the "Wat" video fall into that category. "Things no one would have ever thought to try, yet a dynamic language will fully allow". If you want to point out valid concerns with JS, the double-equal implicit coercion is a far more frightening "gotcha".
Not lexically, no, but dynamically, sure, all the time. JS lets me receive an arbitrary value in a variable `foo`, and "add" it to another arbitrary value in a variable `bar`, without having any opportunity to specify what semantics I mean by "add." Fixing the semantics of the operation is the whole point of specifying it!
Personally, I favor languages that go "almost too far" in the opposite direction, e.g. Elixir. In Elixir, operator[] (a.k.a. the Access protocol) is generic across several types, but the semantics are very strictly constrained; not only does the access have to "mean" getting some kind of element from a container, but it's also only defined where it has a fixed O(1) time-complexity.
This sort of design being conventional in Elixir, means that you can usually predict, just from the lexical environment (a.k.a. "the code on the screen") what the runtime behavior will be of said code—which includes being able to "read off" a time/space complexity for the code—without needing to check how each ADT involved has implemented its generics, let alone having to check for implicit type coercions.
Few people do that outside of code obfuscation contests, but the point is JS has heaps of gotchas like that, each waiting to bite you. How about:
x = 5;
(no var declaration). Extremely easy to do by accident. Lots of these will be left for backwards compatibility. In JS errors often go silent and I developed a strong dislike for any language that does that, including Vimscript and Lua (and I do like Vim).
I'd agree that global declaration is far more egregious. A sibling comment recommends a linter, and I'd probably agree. It's sad that it was ever allowed as one that is copying and pasting code to another location can easily cause this case to happen.
Eh, I actually like JS but I have definitely forgotten to add a "var" or "let" a few times, or sometimes I will do it correctly, get a bit overzealous with cutting, and accidentally remove the initial var declaration.
I'm not saying that it breaks the language, but it definitely is irritating, especially if you're not using a linter.
Whilst I do find it irritating, I don't mind about the scope default so much, but I've certainly run into it (forgetting to specify) a lot.
Mostly because JS is not the only language that I'll be working with at a time, and if I'm dancing between three or four and they have similar syntax, then mistakes creep in.
Javascript is such a good language that, even after two decades of fixes, it's only good when you use a different language - specifically created to address JS's many problems - that compiles to it.
> develop on every platform natively (React Native)
If "native" means bundling a runtime and having your program pass serialized messages to a different thread where the actual native platform code lives, the same can be said for any language. You just need to build the wrappers for the native API – which is a lot of work but could be done for QBASIC running in DOSBox just as well as for JS running on V8.
To dang and the other moderators, can you think of a way to auto-penalize effectively contentless/empty anti-Javascript comments?
Imagine this kind of comment for any other language, C, Python, Ruby, Rust, Scheme whatever. It would be downvoted to death. And yet people still make & upvote these comments about JS despite JS being the most popular language, run on the most devices & having a massive community of people fixing its warts and modernizing JS.
There are still valid critiques of JS but they have nothing to do with Al Pacino or Bruce Willis. Please spare us, or if you want to criticize Javascript, learn something about Javascript in 2019 & criticize that.
I remember finding the SICP in our university’s library as a freshman, me and a friend (both of us had never used scheme) had a lot of fun going through the first chapter together.
I skimmed through the book and think I saw a function declared inside an if-statement. Some JS engines don't like that. And if the engine does support it, the function will be function scoped. To make an if-scoped function, declare it using const f = x => y,
nitpick:
I personally prefer to use intermediate variables instead of nested function calls and ternary operator.
Dont like where they state shit (code, programs, processes etc.) isnt comprise of anything.
Everything is comprised of something.
Please, if you compose something many people could potentionally consume, at least dont be all esoteric and/or mystical about it. This is not a campfire, where everyone tells a story of fairies and shit.
They maybe even more so eager to learn a typical umderlying layer/architecture.
The translation is pretty direct, so the data structures are more idiomatic to Scheme than they are to JavaScript. I think that's OK.