What is not so great is that Google's closure team (not be confused with clojure) decided to remove various functions, making breaking changes - for no obvious reasons other than saving a few lines of code.
Example Things like `goog.isArray` is gone, a library that was adopted by many (including the CLJS compiler) to help smooth out the differences in JS versions and supported features.
The closure team even has great advice for you:
"goog.isArray has been deleted. Use Array.isArray instead."
Well, how about you just delegate to that, Google team, and I can just upgrade?
This kind of library maintenance is what keeps me away from JS/TS where prior investments seem to be less valuable:
React deprecating lifecycle methods, Typescript's breaking changes page is pretty long (but admittedly, being MSFT, they try to care about backward compatibility), Vue.js 3: functional components deprecated, manual changes required.
Who can afford these shenanigans?
Changes in re-frame, reagent etc. have been a lot more careful. Not quite perfect (looking at you Reagent 1.0!), but I'm sleeping much better working with a stable, slow-moving framework - at the cost of maybe a few more repaints.
These are great points. Google's Closure is open source with an Apache 2.0 license [0]. This is a huge ask but do you think a fork of Google's Closure with the goal of minimizing breaking changes be embraced by everyone who currently rely on Google's Closure?
Maintaining backwards compatibility is not trivial as your comment seems to allude to. There's obviously a reason things are deprecated and removed from code bases.
There's also a reason SemVer exists, to notify you to the fact of breaking changes (whether the library maintainers actually abide by the correct usage is another conversation).
Don't want breaking changes? Dont upgrade your stuff, sounds easy to me.
Since this thread/Clojurescript is getting some love I'd like to express something to a hopefully receptive audience:
There was a point where Clojurescript and Javascript sort of walked hand-in-hand during the advent of when React started to make sense in the minds of the community[0].
It felt really exciting because of the cross pollination that was happening between the two languages, Redux felt very familiar, and we have re-frame for clojurescript.
There was a ton of promise with Apollo.js and an improvement on the `connect` functionality by upgrading to a proper query language for getting state into a component versus wrapping functions around multiple `state.some.path` `state.some.other.path`.
David Nolen built om.next around that very idea, it was basically Apollo.js lite, and it was very exciting scientifically but never quite caught on because maybe it was a little clunky. But using datomic pull query syntax to fetch state for use in a component was thrilling. (if you got this far and decided you hate me and your eyes are rolling so hard I get it lol)
And this was all years ago now. All that excitement and progress and effort seems to have been trapped inside of Typescript, and React hooks, and did everyone forget?
I never did try om.next, but to this day Reagent is my favorite way to interact with React. I too was hopeful ClojureScript would become more mainstream. I haven't coded in Clojure in years now because unfortunately I just don't see any companies I did or would work for ever adopting it.
My impression is that CLJS, while an amazing way to write frontends with react, suffered from an incomplete/fractured tooling ecosystem, with the official maintainers leaning on the community to develop the 'batteries' and several good but incomplete and unofficial solutions being offered (lein-cljsbuild, figwheel, boot, etc).
I'm not actively involved with CLJS development anymore but last I checked that still continued, with tools like figwheel/deps.edn/shadow-cljs all sort of doing similar things differently, and there being good-but-not-as-good-as-clojure support in different editors like emacs, intellij and vscode. Similarly, there were a number of different, but still alpha quality ways, to use cljs with react native, all suffering from some major pain points.
I don't have any specific knowledge of the community dynamics you're talking about, but I have opinions about these technologies, and can speculate:
Personally I find it harder and harder these days to justify writing code that doesn't have static types. Even for personal projects, if I'm writing more than 100 lines, I want editor checks and standardized documentation. Particularly when I'm not doing anything wildly novel, and particularly (but not exclusively) for larger projects.
It's not hard for me to imagine industry reaching a similar conclusion, especially when the novelty of most of the web apps being cranked out tends to be lower, and the scale tends to be larger.
And where industry goes, hobbyists tend to go so that they get to put relevant stuff on their resume (not to mention paid employees who release in-house tooling and libraries as open source).
Clojurescript targets/outputs Google Closure compatible code which is easily the most sophisticated JS compiler out there. The reason no one uses it is because writing compatible code by hand is a nightmare.
Clojurescript's front end libraries are incredible, they are basically a better expression of Redux because the Clojure language has constructs that enable a more expressive API https://day8.github.io/re-frame/re-frame/
Clojurescript's JS interop is actually insane, boosted by the quality of Shadow-cljs. You can write 1:1 javascript in clojurescript if you need to. A trite example would be npm installing lodash and writing some code that uses it, I have done this and it just works.
Clojurescript's developer experience with the browser repl is next level. I know a lot of the stuff I'm saying sounds hyperbolic, but I've written a ton of Javascript and react and I really like it still, but using a browser repl to manipulate application state in my editor and reload functions without a full refresh is great.
And I guess lastly, yea the language is awesome. It's basically my perfect version of Javascript. No need to fumble with libraries like immutable.js, no need for additional libraries like ramda or lodash because the standard clojurescript library has everything+.
For me the real advantage is the shared information model with the backend that is trivial to serialize/de-serialize with something like transit-clj(s). It's like the benefit of js/node but with richer data structures: keywords, symbols, sets, maps with arbitrary keys, instants, uuids and extensibility via tagging. JSON is great, but EDN is so much better!
It offers REPL, great hot reloading, a small set of immutable data structures, and a great set of carefully architectured core library functions to work with those data structures.
Also because of immutable data structures it has a very clean comparison semantics e.g. you can compare data structures by value with `=` which helps a lot in React-like environments.
The absence of static typing enables you to write more general code with less effort. All that leads to simple, clean and compact code. If you check Real World App statistics [1] you'll see that Clojurescript/Re-frame implementation has the fewest LOC (almost 4x less than Elm and 3x less than Purescript).
Can share much of the same code on front end / backend. Excellent built-in immutable data structures. Arguably the best modern lisp. Community is usually ahead of its time on state management solutions.
Typescript is probably a better fit for most people doing most things.
IMO. Interactive development. It allows you to connect to a running program (local or remote) and tweak things on the fly. Without even affecting the state of the program. Without even having to save or re-compile. It's hard to explain the benefits of that approach. One has to experience it.
Another major benefit: true code re-use. You can write functions that would work both in Clojure and Clojurescript (even though we're talking about very different environments). With Javascript/Typescript (in practice) that is hard to achieve even when you have a nodejs backend.
The benefits of using Clojurescript over JS/TS in 2021 are superficial and not worth it IMO. Typescript is great, has good tooling and plays nice with the JS ecosystem. With Clojurescript you spent more time fighting integration with the JS ecosystem than getting any real work done. The mismatch between JS objects and Clojurescript data structures is annoying and tedious and riddle with performance issues, and Clojurescript in general has many performance issues.
Absolutely, shadow-cljs is all you need, it's not coupled to the Clojure ecosystem, it uses NPM. I'm actually working on a project that uses clojurscript on the backend which is just a `:node` build target in Shadow.
I’m a bit biased, but from my personal experience I would definitely say that it does. I’ve worked on two projects that had different backends (PHP and elixir) where the choice to use clojurescript IMO was the correct one. Both projects relied heavily on highly interactive frontends that would’ve been a nightmare to write if I had to use vanilla js. If your backend can spit out json, and your frontend isn’t static, then I’d say cljs should be good to use regardless if the backend is clojure or not. However, the biggest pain point for me was the disappointment of not being able to use clojure everywhere in the stack... so prepare for that if it’s the route you choose.
It depends on what kind of project you are using it for.
Hobbyist/toy project - sure, using shadow-cljs you can do your front end entirely in ClojureScript and make calls out to whatever backend you want
Professional project with ClojureScript backend - sure, you can use shadow-cljs to target both node (using :node target) and the browser which will allow you to utilize ClojureScript for full stack and not have to rely on Clojure
Professional Project with non-clojure(script) backend - no. It would not be worth it to spend resources to learn clojurescript (talent pool of existing clojure devs is small) and not taking advantage of full stack clojure(script) can be detrimental
Definitely so. We use Clojurescript with Python backend and it's great. Clojurescript is very good at json processing/manipulating, so it does not matter what backend you have.
If I remember it right, Lumo and Planck (mainly) were created to deal with the long startup times of Clojure. People needed a faster way to get the REPL up and also something that can run tiny scripts. With the emergence of Graal, and tools like babashka, it looks like the JVM warmup time is no longer that big of a problem.
[+] [-] beders|5 years ago|reply
What is not so great is that Google's closure team (not be confused with clojure) decided to remove various functions, making breaking changes - for no obvious reasons other than saving a few lines of code.
Example Things like `goog.isArray` is gone, a library that was adopted by many (including the CLJS compiler) to help smooth out the differences in JS versions and supported features.
The closure team even has great advice for you:
"goog.isArray has been deleted. Use Array.isArray instead."
Well, how about you just delegate to that, Google team, and I can just upgrade?
This kind of library maintenance is what keeps me away from JS/TS where prior investments seem to be less valuable:
React deprecating lifecycle methods, Typescript's breaking changes page is pretty long (but admittedly, being MSFT, they try to care about backward compatibility), Vue.js 3: functional components deprecated, manual changes required.
Who can afford these shenanigans?
Changes in re-frame, reagent etc. have been a lot more careful. Not quite perfect (looking at you Reagent 1.0!), but I'm sleeping much better working with a stable, slow-moving framework - at the cost of maybe a few more repaints.
[+] [-] darksaints|5 years ago|reply
Cljs never should have been built on top of closure.
[+] [-] _e|5 years ago|reply
[0] https://github.com/google/closure-library/blob/master/LICENS...
[+] [-] halfmatthalfcat|5 years ago|reply
There's also a reason SemVer exists, to notify you to the fact of breaking changes (whether the library maintainers actually abide by the correct usage is another conversation).
Don't want breaking changes? Dont upgrade your stuff, sounds easy to me.
[+] [-] pizzeriafrida|5 years ago|reply
There was a point where Clojurescript and Javascript sort of walked hand-in-hand during the advent of when React started to make sense in the minds of the community[0].
It felt really exciting because of the cross pollination that was happening between the two languages, Redux felt very familiar, and we have re-frame for clojurescript.
There was a ton of promise with Apollo.js and an improvement on the `connect` functionality by upgrading to a proper query language for getting state into a component versus wrapping functions around multiple `state.some.path` `state.some.other.path`.
David Nolen built om.next around that very idea, it was basically Apollo.js lite, and it was very exciting scientifically but never quite caught on because maybe it was a little clunky. But using datomic pull query syntax to fetch state for use in a component was thrilling. (if you got this far and decided you hate me and your eyes are rolling so hard I get it lol)
And this was all years ago now. All that excitement and progress and effort seems to have been trapped inside of Typescript, and React hooks, and did everyone forget?
0: https://swannodette.github.io/2013/12/17/the-future-of-javas...
[+] [-] city41|5 years ago|reply
[+] [-] pandeiro|5 years ago|reply
I'm not actively involved with CLJS development anymore but last I checked that still continued, with tools like figwheel/deps.edn/shadow-cljs all sort of doing similar things differently, and there being good-but-not-as-good-as-clojure support in different editors like emacs, intellij and vscode. Similarly, there were a number of different, but still alpha quality ways, to use cljs with react native, all suffering from some major pain points.
[+] [-] frankiesardo|5 years ago|reply
https://book.fulcrologic.com
[+] [-] brundolf|5 years ago|reply
Personally I find it harder and harder these days to justify writing code that doesn't have static types. Even for personal projects, if I'm writing more than 100 lines, I want editor checks and standardized documentation. Particularly when I'm not doing anything wildly novel, and particularly (but not exclusively) for larger projects.
It's not hard for me to imagine industry reaching a similar conclusion, especially when the novelty of most of the web apps being cranked out tends to be lower, and the scale tends to be larger.
And where industry goes, hobbyists tend to go so that they get to put relevant stuff on their resume (not to mention paid employees who release in-house tooling and libraries as open source).
[+] [-] frankiesardo|5 years ago|reply
On the ClojureScript side, I would like to see more projects integrating with platforms like Nextjs and Gatsby.
[+] [-] robertlagrant|5 years ago|reply
[+] [-] systems|5 years ago|reply
Clojurescript is dynamic, beside the lisp syntax which is arguably cleaner, and offer some nice advantages like homoiconicity
What is the real advantage of Clojurescript (?)
[+] [-] pizzeriafrida|5 years ago|reply
Clojurescript has the best client-side build tool I have used in https://shadow-cljs.github.io/docs/UsersGuide.html and everyone uses it.
Clojurescript targets/outputs Google Closure compatible code which is easily the most sophisticated JS compiler out there. The reason no one uses it is because writing compatible code by hand is a nightmare.
Clojurescript's front end libraries are incredible, they are basically a better expression of Redux because the Clojure language has constructs that enable a more expressive API https://day8.github.io/re-frame/re-frame/
Clojurescript's JS interop is actually insane, boosted by the quality of Shadow-cljs. You can write 1:1 javascript in clojurescript if you need to. A trite example would be npm installing lodash and writing some code that uses it, I have done this and it just works.
Clojurescript's developer experience with the browser repl is next level. I know a lot of the stuff I'm saying sounds hyperbolic, but I've written a ton of Javascript and react and I really like it still, but using a browser repl to manipulate application state in my editor and reload functions without a full refresh is great.
And I guess lastly, yea the language is awesome. It's basically my perfect version of Javascript. No need to fumble with libraries like immutable.js, no need for additional libraries like ramda or lodash because the standard clojurescript library has everything+.
[+] [-] slifin|5 years ago|reply
So nice to have a good standard library when using JavaScript
My favourite "type checker" is clj-kondo
[+] [-] divs1210|5 years ago|reply
Reagent and re-frame have been awesome since Day 1, even as react has tried to play catch-up with hooks etc.
[+] [-] djblue|5 years ago|reply
[+] [-] achikin|5 years ago|reply
Also because of immutable data structures it has a very clean comparison semantics e.g. you can compare data structures by value with `=` which helps a lot in React-like environments.
The absence of static typing enables you to write more general code with less effort. All that leads to simple, clean and compact code. If you check Real World App statistics [1] you'll see that Clojurescript/Re-frame implementation has the fewest LOC (almost 4x less than Elm and 3x less than Purescript).
[1] https://www.freecodecamp.org/news/a-realworld-comparison-of-...
[+] [-] cliftonk|5 years ago|reply
Typescript is probably a better fit for most people doing most things.
[+] [-] shaunxcode|5 years ago|reply
[+] [-] iLemming|5 years ago|reply
IMO. Interactive development. It allows you to connect to a running program (local or remote) and tweak things on the fly. Without even affecting the state of the program. Without even having to save or re-compile. It's hard to explain the benefits of that approach. One has to experience it.
Another major benefit: true code re-use. You can write functions that would work both in Clojure and Clojurescript (even though we're talking about very different environments). With Javascript/Typescript (in practice) that is hard to achieve even when you have a nodejs backend.
[+] [-] ebruchez|5 years ago|reply
https://www.scala-js.org/
[+] [-] unknown|5 years ago|reply
[deleted]
[+] [-] Scarbutt|5 years ago|reply
[+] [-] ragnese|5 years ago|reply
[+] [-] pizzeriafrida|5 years ago|reply
[+] [-] sometimesweenie|5 years ago|reply
[+] [-] jetti|5 years ago|reply
Hobbyist/toy project - sure, using shadow-cljs you can do your front end entirely in ClojureScript and make calls out to whatever backend you want
Professional project with ClojureScript backend - sure, you can use shadow-cljs to target both node (using :node target) and the browser which will allow you to utilize ClojureScript for full stack and not have to rely on Clojure
Professional Project with non-clojure(script) backend - no. It would not be worth it to spend resources to learn clojurescript (talent pool of existing clojure devs is small) and not taking advantage of full stack clojure(script) can be detrimental
[+] [-] erikcw|5 years ago|reply
[+] [-] achikin|5 years ago|reply
[+] [-] billfruit|5 years ago|reply
[+] [-] rcarmo|5 years ago|reply
[+] [-] iLemming|5 years ago|reply
[+] [-] pizzeriafrida|5 years ago|reply