This was the final push I needed to learn Clojurescript.
Absolute awesome work.
I always kept my distance from Clojure because of the reliance on the Java ecosystem but having a productive and stable language that is a pleasure to work in and that transpiles to JavaScript seems like a good deal. Plus a solid REPL-based workflow and rapid prototyping support, something I sometimes miss from more static languages.
I love the idea of making code and data alive, interactive and illustrative. Reminds me a bit of Bret Victor's talks, essays and prototypes illustrating how interactive, graphical thinking can enhance understanding and even creation.
Imagine our editors doing this by default, what it would mean for documentation, code quality and enhancing our ability to understand and communicate these concepts with augmented code.
Shaun Lebron has a bunch of interesting stuff on his github[0]
involving closurescript.
I haven't toyed with closurescript yet, if anyone has any experience with it, what are its strengths and weaknesses? I'
ve been learning scheme/racket for the past year and for learning purposes Dr Racket is more than enough for now, but sometime in the future I'd like to branch out of that.
- Low changes/grow. This demo was written in 2014 and it probably still look like as if it had been written in 2020.
- Easy interop with any npm library. Just import and use it.
"It has a slow startup time. Clojure runs on the JVM and has a significantly slower startup time compared to Node. Again, this is only a problem from an outsider’s perspective. We have REPL. You start the app only once, and it keeps running in the background. You can interactively include new changes, without having to startup every time."
I've been using Clojure for about 8 years and this is one of the talking points I find most annoying. The slow startup time is a disadvantage, and it should be owned. It disqualifies clojure from a large class of applications and if you're not honest about it you lose credibility, and you retard potential attempts to solve it. It doesn't mean you can't write software with Clojure, but be honest about the fact that it makes lots of types of usage (not all) a poor match.
Right. I find it annoying too, but for the opposite reason.
Since GraalVM, Babashka, and before them Lumo and Planck, or just plain CLJS + NodeJS, Clojure (the language) has several answers to those use cases, and it’s unclear to me at least why this is a point of contention regarding Clojure (the JVM implementation). Should we also bash CLJS for being single threaded?
And now that it's honestly approached as a potential issue, you can talk about the tradeoffs involved here. I haven't followed those projects closely so correct me if I'm wrong, but Babashka is an interpreter that implements a "substantial subset" of Clojure, right? GraalVM seems amazing, but it also is not a guaranteed seamless experience, either (no eval, partial support for reflection).
The faster startup time is one reason I've thought that clojurescript on Node (shadow-cljs makes this really easy) could become more popular than Clojure Classic.
There are several tools available for live-coding (REPL-driven development) such as more recent shadowcljs or the older Figwheel.
Rum is a powerful wrapper over React.js and you can live code and see instantaneous results in the browser (using shadowcljs or figwheel).
ClojureScript's strengths largely stem from Clojure -- collections as fundamental types, REPL, macros, immutable datastructures* and lovely syntax.
As far as cons go, it takes some time to start up a REPL and making release builds is an extra step, but should work just fine unless you're a newbie like me and you leave strange unnecessary lines in your code. Javascript and js/CSS interop is there, but it's not super obvious and takes some getting used to what it looks like -- luckily there are enough online writeups to make that process easier.
The addage "why clojurescript? Because clojure rocks and javascript reaches" sums up nicely the motivation.
You can have largely isomorphic code on the front-end and back-end, which lends nicely to creating server-side rendered versions of SPAs for search engine indexing and fast load times. However, the server-side copy and the client rendered copy must match exactly for this to work, which can be a bit of a "thread the needle" kind of problem.
* immutable datastructures are awesome, contrast with mutable datastructures and "location oriented programming" -- any time you "edit" a value you're actually creating a new datum. This is done with atoms (immutable data stores that need to be dereferenced to retrieve their value) and operations such as swap! and reset! that either apply a function to the current value of an atom, resulting in a fresh new atom with the new value, or overwrite the atom completely with some value, respectively.
So yeah, if you like live-coding and appreciate the power of lisp, it's a really nice fit. Yes, the way to do stuff is "opinionated" but it's opinionated in what many years of trudging through the tar pit* would suggest is the right (only?) way to do things.
As you, I learned scheme first, chicken scheme! I like CLJS, your code will likely be small and expressive. The hot reloading another multiple of productivity added. And having a REPL that can connect to the browser is great. But CLJS has some pitfalls.
It's JS underneath so you still need to know it. Because eventually there is a large enough problem someone else solved and you need to understand their code, shipped as a npm package. When you are solving some problem and researching, most people use JS, so you will have to go through the extra step of translating JS code in your head to CLJS. This could be anything from browser quirks to React Native workarounds.
I don't think the tooling is enough for when complexity grows. It can be difficult to quickly understand how the code glues together, finding references to functions and refactoring. It is a dynamic language, and have all the problems that comes with that.
My assessment is that if you are making a browser only fronted with reagent (and reframe) and limited scope. Of course having a backend in either CLJ or CLJS as well to benefit the most.
It does. <! reads from a channel that closes in the specified timeout. It is non-blocking. (similar to the away/async JS magic - rewrites the go block to a state machine)
Absolute awesome work.
I always kept my distance from Clojure because of the reliance on the Java ecosystem but having a productive and stable language that is a pleasure to work in and that transpiles to JavaScript seems like a good deal. Plus a solid REPL-based workflow and rapid prototyping support, something I sometimes miss from more static languages.