
Why ClojureScript Matters - jonpither
http://blog.juxt.pro/posts/why-clojurescript-matters.html
======
manishsharan
I think that the main argument presented in this blog -- "avoiding splitting"
is wrong :Splitting the development into frontend and backend is essential for
developing maintainable code for large projects. Having a well defined
communication api between backed and frontend defines responsibility for front
end and backend developers and also enable better (j)unit test cases. The
communication overhead and associated documentation is beneficial in the long
run as the code that is produced will be better understood by all , not just
the lone developer; it also makes code reviews easier and allows new
developers to take over existing code base when necessary. It is immature to
think developers will only feel pride in their when they own the entire
codebase, the ui-to-db stack; The idea that "Lovingly crafted aesthetics in a
codebase is key" is silly; code needs to be testable, well documented and
highly optimized and re-usable.The "jostling of positions" are design
discussions and they are important part of the software development cycle.

I like Clojure and I am interested in learning ClojureScript but this blog
post makes a poor case for it.

~~~
bryanlarsen
Sure, any large code base needs to be modular, but why impose an arbitrary
split?

We've got a large Node.js codebase. Some of the code runs only on the server,
some runs only on the client, but the majority runs on both. Our code is split
into modules for functional reasons.

~~~
Kiro
> but the majority runs on both

What does this mean exactly? What kind of code needs to run on both?

~~~
netcraft
I tend to agree with you, but there are things that can/should run on both -
validation of input for one. But I'd like to hear other things - I hear "use
the same code on the server and client" all the time, but I haven't found a
lot of use for that personally.

~~~
girvo
Turning a reactive web application into a regular "web site" \-- ie. allowing
you to use the bulk of the application without Javascript enabled. Great for
SEO, too, at least until Google gets Javascript execution further along (which
it's certainly doing, and getting better every day).

------
pbowyer
I disagree with some of the statements about developer pride. I was reading
[https://speakerdeck.com/garann/code-is-a-
job](https://speakerdeck.com/garann/code-is-a-job) this morning and it's a
position I have a lot of sympathy with.

Not having the backend developer/fronted developer split is good; while each
will have its own specialities, they shouldn't be siloed into separate teams.

~~~
qzcx
Thanks for sharing. Good read.

------
jwr
As a data point, I've just written a significant ClojureScript application,
using React (Rum for bindings, Datascript for client-side db). It's amazing
how quickly one can create complex apps with impressive performance out of the
box.

If you haven't used ClojureScript, it is _definitely_ worth looking at.

~~~
javajosh
How did you select your components? I've never heard of Rum or Datascript, for
example.

~~~
straws
Nikita Prokopov has presented a pretty cohesive vision for front-end
programming in the cljs community. Even if you don't agree with all of his
opinions, he's one of the only people assembling a big picture about how to
write apps in this way. It's worth reading his blog:

[http://tonsky.me/](http://tonsky.me/)

An emphasis on low-level tooling and not enough discussion around high-level
architecture/examples has hurt the react+cljs combo adoption from my point of
view. It's the nature of Lisp to come up with your own abstractions around
application architecture, but the community would be wise to talk more about
solving common web patterns and how to cleanly break away from those patterns
when necessary.

~~~
KurtMueller
Thanks for pointing me to his blog. He's a great read. Got anything else by
him I should read/watch/listen?

------
Frozenlock
If Om hurts your brain, I can't recommend Reagent enough: [http://reagent-
project.github.io/](http://reagent-project.github.io/)

~~~
bostonOU
Can you explain why Om hurts your brain? I've heard other people say similar
things, but I've never quite understood why. Is it cursors? Local component
state?

~~~
MikeOfAu
OM components are complex. There are global transaction/message channels,
component local state, an OO backpane, lifecycle functions, functional
zippers, hierarchy organised data, etc. I can't understand how anyone could
claim it to be simple.

Look at this example code, apparently held in such high regard that it is
referenced off the front page of OM: [https://github.com/swannodette/om-
sync](https://github.com/swannodette/om-sync) To me that is a ghastly,
inexcusably complected hairball.

Don't get me wrong. I really like clojurescript. I program in it daily, on
purpose. It is just that I'm shocked at the level of devotion and adulation
for OM when there are really lovely alternatives like Reagent and Rum.

~~~
swannodette
Some inaccuracies here about Om. There are no message channels. There are no
functional zippers. Component local state and lifecycle are critical React
integration points. Hierarchy organized data is not required - people have
succeeded at integrating DataScript. om-sync isn't even an official thing,
just got tired of people asking me about a basic example :)

If you don't like Om, that's really OK. The real goal of Om was always to
inspire people to consider and research alternatives to traditional client-
side MVC. 16 months in I would say with the large number of excellent
alternatives, Om very much succeeded.

I hope Om Next accomplishes the same broad goal and convinces people to
seriously consider the big ideas behind Relay/GraphQL, JSONGraph/Falcor, and
Datomic.

~~~
thiago_fm
I also feel that Om is very complex. I'm sure I've spent over 20 hours trying
to wrap my head around it but didn't manage to do anything.

From the people that know it well, they all love it. But I don't seem to have
the required knowledge to understand it. I feel somehow dumb by that. The docs
aren't good also.

After that, I've tried reagent for 30 minutes and ended up with a lot of
progress and I'm currently writing my first cljs small app. Everything seems
to work and it's like clojure.

You have an atom and just have to write views in a hiccup style, everything
magically works.

Maybe I will try Om later and get it, but it's not simple. I've been able to
wrap my head around a lot of concepts with easy in my life, but Om felt too
much.

~~~
sgrove
Pairing with someone who's built a few Om apps should get you up to speed in
no more than 45 minutes. I've done it a few times now, and it just takes a few
examples, building some components, and composing them together.

~~~
thiago_fm
I don't know anyone with interest in Om/clojure though :(

------
mikerichards
_Taking the 'splitting' argument head on, I don't believe that having a
planned split between 'front end' and 'back end' developers is a good idea at
all._

I don't like that he seems to have to concoct that argument to sell
ClojureScript. The argument seems artificial.

There's lots of reasons to decouple the front-end development from backend
development. In fact, once you start using a client framework and use the
backend as a service layer you can really decouple your layers. Doing web
stuff, I primarily work in ASP.NET MVC and I'm trying to get rid of razor
completely.

In fact, If I had my way, I'd have css/photoshop jockeyes (with a little
angular/whatever knowledge) in charge of the client, a javascript/Typescript
guy doing the client MVC, and a data guy doing Web API.

Agile tends to frown on these distinctions. I don't buy it , just like I don't
buy a lot of the Agile dogma. Oh well.

------
serve_yay
I notice the author employing a bit of jiu-jitsu I see sometimes -- basically,
that you shouldn't worry about designers not understanding ClojureScript (or
whatever), because that is insulting to the designers.

But how about designers have 18,000 other things to deal with and maybe they
aren't interested in learning (in their estimation) the latest wacky-ass way
web developers invented to generate HTML. The point isn't that they couldn't
understand it if they tried, the point is that they would have to try, perhaps
to the exclusion of something they would consider more useful.

~~~
Skinney
I agree with this. The author should've mentioned enlive (you got a similar
library that supports om) which allows html to be html, which should make
designers happy.

------
saosebastiao
So I tried Clojurescript and I liked it as a language. In terms of fit for a
compile-to-Javascript language, it is probably the best implementation out
there, partially due to Javascript's dynamic lispy origin. But it has a a
major problem: It's not Clojure. It might be a Clojure-like language, but its
not Clojure. So you still end up "splitting", but when you split you have to
squint harder at the details. As far as fidelity to the native language, I've
found Scala.js to be much better.

I can't wait for WebAssembly though... it will be a game changer for people
that prefer strong static typing for managing logical complexity.

~~~
malcolmjuxt
I haven't used Scala.js, but I find Clojure and ClojureScript to be so damn
close to identical I'm surprised at this comment. When I'm doing
ClojureScript, everything I use from syntax, sequences, persistent data
structures, core.async, protocols and records (the list seems endless) is the
same as Clojure. The only thing that trips me up is regular expressions. In
fact, I find there's a great deal more difference in the Scala written by any
given two Scala developers than between Clojure and ClojureScript.

------
chowes
I've come to appreciate some of the new ES6 features (anonymous functions,
lets) much more after using their equivalents in ClojureScript.

Also, The interactive REPL based workflow that a lot of the LISP languages
utilize is extremely appealing. I've been thinking a lot about how to bring
this back into the JS world. I have yet to find any good literature on it, but
I will be exploring this area more.

For those curious, here are some blogs that convinced me to finally give
Clojure a spin:

\- [http://rigsomelight.com/2014/05/01/interactive-
programming-f...](http://rigsomelight.com/2014/05/01/interactive-programming-
flappy-bird-clojurescript.html) (seems like this is the stereotypical "you
should try ClojureScript because... " post)

\- [http://thinkrelevance.com/blog/2013/06/04/clojure-
workflow-r...](http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-
reloaded) (a bit code-heavy, but an admirable workflow)

\-
[http://swannodette.github.io/2013/11/07/clojurescript-101/](http://swannodette.github.io/2013/11/07/clojurescript-101/)
(dealing with asynchronous code)

I'm curious HN, anyone out there making strides in interactive JS development,
akin to the 2nd blog post I referenced above?

~~~
smrtinsert
Honestly this is the part I hate most about Clojure. The tooling is always so
convoluted to setup and by the time you start your next project something has
changed again, requiring more changes which might break your tool chain.
ClojureScript is especially guilty of this right now with all the recent repl
changes.

I appreciate the The CS team trying to work with 3rd party repl developers
right now, but it doesn't seem to be helping much. It's pushed me back to
simple gulp based es6 dev using ramda, rxjs, immutablejs, etc - basically the
parts of clojurescript I like. The only thing I sort of miss from Clojure are
macros and homoiconicity - it sure is nice to look so uniform, but the tooling
just drives me away.

~~~
mordocai
I can agree with that with clojurescript, but I disagree that clojure itself
has this problem.

Clojurescript -should- be calming down soon. It is in a stage of changing
constantly ATM but that should calm down once some of the underlying tech is
stabilized (like clojurescript bootstrapped from clojurescript).

~~~
sgrove
I get the same impressions. Even working with ClojureScript professionally for
~3 years, contributing to the compiler (a tiny, tiny bit), and diving deep
into a lot of the libraries... the tooling story is way too chaotic for me.

But I'm somewhat OK with it, as the changes generally seem to be positive, and
I have hope that the stability will coalesce around a good, rather than
rotten-but-papered-over, core.

~~~
sbensu
I feel the same way. The ClojureScript compiler routinely makes the
conceptually sound choices even in the face of breakage. This leads to
unstable tooling but the quality of the underlying code allows for bigger and
better conceptual improvements.

------
bryanlarsen
Much more relevant than WASM in 2015 is that modern Javascript development is
also moving towards compilation. There's little fundamental difference between
compiling ES7 via babel.js vs compiling clojurescript.

~~~
serve_yay
I had a similar thought, though for me that's a reason to keep using Babel and
ES.next rather than ClojureScript. I find lispy syntax difficult to read.

------
Touche
One thing Clojure/ClojureScript desperately needs is an answer for
progressive-enhancement.

~~~
emidln
No it doesn't. You can literally do the same thing you did with PHP in 2007 if
you want to (have a controller that outputs xml to be transformed into jquery
commands if an ajax call or renders html if not ajax). You could also do
something less silly like share your templates (maybe via hiccup and its many
cljs implementations or via enlive/enforce/kioo (or via Soy, or anything else
really)). If you want to get really fancy, you can actually just render your
js server side via nashhorn and then rebind whatever modern rendering library
you choose (React, Ember, etc) onto the rendered html at runtime. This is all
ignoring the fact that nothing prevents you from serving html from server-side
templates and keeping your cljs codebase completely separately ala most web
apps (then progressively enhancing with whatever you normally would).

~~~
Touche
It really does. Isomorphic is the new standard. Doing it in a very manual way
is not good enough. Every new JS framework is expected to do this out of the
box and the older frameworks are scurrying to gain support.

~~~
emidln
React literally does this out of the box. Om does it (based on react). Reagent
does it (based on react). Using js/React (raw js interop) does it. There is
actually nothing to do. You exec your js in a nashhorn thread. That gives you
some html. You ship it your browser on initial GET, then initialize react on
it.

This is identical to what you'd be doing on react+node. With a macro or two,
it's easier than anything node provides.

As an aside, isomorphic isn't a new anything. We were rendering pages on the
server, rendering updates on the server with the same templates, sticking them
in xml representing jquery dom manipulation, and pipelining those in a single
request since at least 2007 (when I first encountered the technique and
shipped with it, I believe we used a javascript library called Taconite, maybe
since 2005 from looking at the sourceforge account). Progressive enhancements
were rendered off the same templates and inserted asynchronously,
automatically, based on whether the controller on the server detected it was
an ajax request or a bare GET. This incidentally made things very cacheable.

~~~
escherize
Do you have a link to these macros?

~~~
fnordsensei
Here's a spot to start from:
[https://github.com/DomKM/omelette](https://github.com/DomKM/omelette)

EDIT: The example in the link provided builds on the now deprecated CLJX, so
it's not entirely up to speed. (CLJX was the way to write clj/cljs in the same
codebase until "reader conditionals" came along).

------
bobajeff
By the time JavaScript is being compiled down to WebAssembly you'll probably
also be able to have the full Clojure, Scala, Java and other JVM based
languages (also .Net languages) compiled down there as well.

~~~
aardvark179
That's going to be long time coming. To be a suitable target for higher level
languages wasm is going to have to gain GC, method dispatch instructions
(preferably with the sort of machinery invokeDynamic on the JVM provides,
because method dispatch isn't identical across languages), dynamic code
loading, threads, and probably a bunch of other stuff.

Wasm is definitely a good start, but it is only a start right now. It's a good
target for AOT languages, but really not suitable for interpreted or JITed
ones right now.

~~~
eropple
I'm not sure why you say that a traditionally JITed language won't benefit
from this. We've had AOT compilers for the JVM and for .NET for years.

The perf may be slightly worse, but we've had good-enough perf forever.

------
rymndhng
I'm still waiting for stable tooling support. With Clojure 1.7, the
introduction of Reader Conditionals via `.cljc` is a step in the right
direction.

The tooling still isn't quite ready yet. I've tried porting some `.cljx` code
over, but it's not quite working for me yet with leiningen.

------
maleghast
Really enjoyed reading this, Jon, thanks for sharing it :-)

If nothing else it has added another unit of weight to the idea that I need to
adopt CljS quickly before I am left completely behind. Now all I need is a
project and more free time than I currently have... ;-)

------
Cshelton
While clojureScript is awesome and gets you to think differently when writing
javascript, I think a more interesting thing people should check out it es6
(or ecmascript 6, or es 2015, w/e it's called now.). It brings many new things
to javascript that people from other languages will be used to...likes the
"class" syntax. Right now you can write near 100% es6 standard with a pre-
compiler. Most use babel. Soon it will run on all the latest browsers without
though, making it far better to write then a language that compiles to JS. JS
is nice now, I know I know, just give it a try =p

Also, another thing to look at is eithe Facebook's flow or Typescript. It adds
some type checking, really great. Especially if you are writing server side in
Node.

~~~
warfangle
'class' is one of the most commonly mentioned but least useful constructs
available in ES6. Things that win out over it? Destructured assignment, sane
module syntax, arrow functions, true block scope variable declaration, and
constants.

~~~
Cshelton
Yes, but people coming from java or c# or something will like it. Despite it
being just syntactical sugar. I wasn't about to list out all the benefits of
es6, that would take several entire blog posts.

~~~
jeremiep
I would rather see ES6 with no class support whatsoever and having people
learn to code without them instead of adding features to satisfy the lowest
common denominator.

I've used classes in CoffeeScript and regretted it every single time. Once
your web project starts to grow in scale classes quickly become your first
pain point. Especially given how functional JS libraries have become nowadays.

~~~
warfangle
Composition over inheritance wins, so hard.

(edit: downvote for a typically well-thought-of idiom, especially with regard
to a language like js? .. if you disagree, why not talk about it?)

~~~
Touche
Classes are unavoidable in JavaScript if you care about performance.
Recreating redundant functions inside a closure in performance critical code
is a sure way to have slow apps.

~~~
jeremiep
Creating an object and creating a closure both need to allocate memory in the
VM, but the closure doesn't need to expose its internals the way an object
does and therefore can be further optimized by the runtime.

If you need to write performance critical JavaScript, then allocating new
objects will be just as slow as creating new closures. In either cases you
should allocate them ahead of time and then closures are still the clear
winner.

~~~
warfangle
> Creating an object and creating a closure both need to allocate memory in
> the VM, but the closure doesn't need to expose its internals the way an
> object does and therefore can be further optimized by the runtime.

Actually... creating an object instance via a constructor lets the runtime use
an internal class, which improves performance (as long as you don't modify its
properties post-construction). This is a well-known aspect of V8 performance.

~~~
jeremiep
Even with an internal class you're still doing lookups for properties. A
closure can instead use local variables which are accessed by index. Why do
you think its good practice to pull properties out of objects and into local
variables before a tight loop?

