
What Holds Me Back from ClojureScript - jaredly
http://jaredforsyth.com/2015/11/26/What-holds-me-back-from-Clojurescript/
======
dr_win
Good points. I started with ClojureScript earlier this year and I agree with
your article. But for me ClojureScript is still much better option than
staying in JavaScript land. Performance will be solved over time with faster
machines (I've purchased high-end iMac recently, so I don't feel such pain
:-). Workflows for incremental compilation like Figwheel also help a lot. And
I think there is a great promise that tooling will evolve quickly.

I'm the author of cljs-devtools. I think for development it is perfectly fine
to use Chrome Canary. Also I would recommend you to check out this article:
[https://github.com/binaryage/cljs-devtools/wiki/Figwheel-
REP...](https://github.com/binaryage/cljs-devtools/wiki/Figwheel-REPL-plugin).

My public projects so far:

[https://github.com/binaryage/cljs-
devtools](https://github.com/binaryage/cljs-devtools)

[https://github.com/binaryage/chromex](https://github.com/binaryage/chromex)

[https://github.com/darwin/plastic](https://github.com/darwin/plastic)

[https://github.com/darwin/faceboard](https://github.com/darwin/faceboard)

[https://github.com/binaryage/pure-frame](https://github.com/binaryage/pure-
frame)

~~~
jaredly
Awesome! Thanks, I've been looking around for good projects to check out and
hack on.

------
erikcw
We have a good sized clojurescript SPA in production, and it has been a real
joy to work with. We are using Reagent, which when coupled with FigWheel[0]
goes a long way toward mitigating slow startup, as well as "tooling" issues in
general. The live reloading is a fantastic experience.

Sourcemaps have been a big help for debugging in general, though we have had
several instances of bugs taking a bit of effort to get to the bottom of
because of some deep javascript stacktraces -- for the most part the java side
of the compiler hasn't been a big deal. Many of these have been type related
bugs, so we're looking into adding some schemas[1] going forward where it
seems appropriate. Despite those issues, it has overall been a huge
productivity boost. We've also witnessed this story only improving with time.

The community truly is fantastic. Lots of very smart, friendly folks doing
interesting things.

[0] [https://github.com/bhauman/lein-
figwheel](https://github.com/bhauman/lein-figwheel) [1]
[https://github.com/Prismatic/schema](https://github.com/Prismatic/schema)

~~~
sotojuan
Also look into Devcards[1], looks interesting.

[1] [https://github.com/bhauman/devcards](https://github.com/bhauman/devcards)

------
rlander
Let me just preface this by saying that I've written Clojure in anger for the
past 5 years and I agree with all of the author's points.

I love writing Clojure(Script) code, but I hate reading it. It fits perfectly
with the way I think (when I'm writing code), but horribly with the way I try
to understand code I wrote months ago.

With that said, the emergence of Elm as a viable alternative to front end
functional programming has pushed all my new projects away from ClojureScript.
Now, for the author's CS complaints, Elm has:

* Fast compile times, startup time indistinguishable from JS.

* Great error messages.

* Imature tooling, but that's changing quickly.

* Static type checking.

So, maybe op should give Elm a try.

[Edit: clarification]

~~~
jaredly
I was going to have a section on Elm, and then the post got too long :)
Clojure(script) feels much more mature, and general-purpose. Elm is client-
only, not nearly as many libraries, etc.

Would clojure's readability be helped by having a non-lisp pretty-printer?
I've been thinking about this a bit - s-exps are great for writing, but fails
to take advantage of our advanced visual pattern matching when reading it.

~~~
rlander
Cool, do write about your Elm experiences, I'd be interested to read!

Unfortunately, yes, Elm is restricted to the browser. But this might change in
the future. And although it is somewhat tedious to write ports, IME Elm
communicates better with JS than ClojureScript. You can just drop any old JS
library and write a port for it (it will be async, though).

Sexps alone don't bother me at all. What bothers me (and I only came to this
conclusion recently, after reading this[0]) is the interplay between
functional code and the absence of type annotations. Sometimes it feels like
Lisp just _wants_ you to write clever code, all the time. Clever Python code
looks bad. Clever Lisp code looks pretty nice.

[0] [http://elbenshira.com/blog/the-end-of-dynamic-
languages/](http://elbenshira.com/blog/the-end-of-dynamic-languages/)

~~~
gered
It's interesting to hear from someone else who also finds that Clojure/Lisp
code can be difficult to read. I worked with Clojure professionally for 2
years and had started to think that I was the odd one out since everyone else
I worked with was just gushing over the readability of the code. At times it
could be easy to read, but very often I found it hard to follow and would have
to spend more time then others deconstructing what was happening.

Which is not to say that I didn't like working with Clojure. I very much did.
But it always seemed to be such a chore to read others code or code I hadn't
seen in a few months or more. I remember on occasion showing some snippets of
code to a co-worker and commenting that I thought there was too much "clever"
code in there, that it was too dense and hard to follow. The co-worker didn't
agree with me though, and I guess I just resigned myself to the idea that I
was the odd one out here or something.

Ultimately, I think I ended up coming to the same conclusion as you. My way of
thinking (and reading code apparently) just clicks so very much better with
typed languages.

(I hope no one reads my post and treats this as some kind of attack on
Clojure/Lisp and s-exps. It's not. I'm just noting that the style just doesn't
jive with certain types of people. And I gave it plenty of time (2 years as
noted above) before coming to that realization.)

~~~
rlander
And I thought _I_ was the oddball ;)

Yup, sometimes it's easier for me to understand somebody else's OCaml/F#/Elm
code than Clojure code written by myself. I still love working with Clojure,
though. Go figure...

------
dustingetz
I think this article is very fair and, today, you know you are ready for cljs
when you no longer value all these things over the pure elegance and
simplicity and power of great clojure code, which JavaScript doesn't even
approach even with React and es6. The type of person who chooses to write cljs
is someone who values code elegance and abstraction power above all else at
any cost, and, indeed, pays that cost every day when they try to debug
core.async, or try to get a newbie's machine up and running (you end up
apologizing 10 times about the fragile tooling and then a hundred more time
for the horrible stack traces... I hosted clojure katas for beginners at a
meetup last night so this issue is particularly fresh) I could go on. But in
the end it is so worth it to me because the raw power of clojure just hits all
the high notes in my brain in ways no other language has.

------
edko
ClojureScript has some very powerful tools available (figwheel, om/next), and
the community is working on resolving many of the issues mentioned in the
article. Derek Slager's presentation "ClosureScript for Skeptics" is really
good and covers many of these topics
([https://www.youtube.com/watch?v=gsffg5xxFQI](https://www.youtube.com/watch?v=gsffg5xxFQI)).

Myself, I prefer ScalaJS because I already know Scala, the tooling is
excellent, it is fast, and the resulting JS is of reasonable size.

Fortunately, it is not an either/or decision. Both compile to JS and can
interoperate without too much effort.

------
grayrest
I was roughly where you were at the beginning of the year. I've been in and
out of the Clojure community for a couple years and decided to take a job
writing clojurescript full time. App is around 15k loc and was initially in Om
and has now been migrated to (my fork of) re-frame.

Positives: <3 re-frame. It's the first architecture in 15 years of frontend
dev that I've been happy with and I've tried pretty much everything. cljs is a
better language than es6. I like devcards.

Negatives: I've put two work weeks into dealing with tooling problems. I have
a 5 minute build. This mostly doesn't matter because incremental builds but
every so often (e.g. Tuesday) I hit a problem and have to bisect with a fresh
build at each step.

While I'm happy with the language, I'm less happy than I expected to be. I'm
in the process of porting devcards and re-frame patterns to (functional)
Typescript for my personal projects. The language is a significant barrier to
contribution from a larger community and I get a bigger lift from optional
types+autocomplete than I do from protocols and macros.

Edit: Is anybody interested in a set of Sublime-ish keybindings for Cursive? I
made the set for my coworkers and for the things I can't do via IdeaVim and
they've been working fairly well for the past couple weeks.

~~~
swannodette
5 minutes for a 15KLOC project seems pretty strange to me unless you're
building on a machine with very limited CPU/RAM. Make sure you're giving the
JVM enough RAM. Also the next release of ClojureScript supports parallel
builds, I've consistently seen users report 30%-300% faster builds (depends on
# of cores, dependency graph).

~~~
grayrest
This is on a 2012 MBA for a prod build. I see times of 140s or 180s on a fresh
dev build. Times are lower on faster machines but still in the multiple-minute
range. I'll tweak the build JVM settings tomorrow and see if that improves
things.

~~~
swannodette
Yeah just doesn't sound plausible to me. I've seen bigger projects take less
than a minute on a 2014 desktop.

For big prod builds you'll definitely want to give the JVM at least 1gb of
RAM, make sure you actually override Lein's defaults:

    
    
        :jvm-opts ^:replace ["-Xmx1g" "-server"]

~~~
lgas
Just as another data point, our project is 16k lines (including tests) and I
just timed it at 2.7 minutes to run "lein cljsbuild once" with no difference
when setting those jvm-opts. This is on a quad core 2.8ghz i7 MBP.

~~~
swannodette
:compiler-stats has been a thing for a while now. This would give more
information - like how much time in ClojureScript vs. advanced compilation.
Also the compiler version matters - 1.7.170 is what you want to use. Otherwise
you may need :recompile-dependents false.

~~~
lgas
Cool. I did not know about :compiler-stats. I'll check it out.

------
venantius
There are a few weird conflations in this article that I think could use a bit
of cleaning up. Why is om/next being compared to Falcor and Relay? Om in
general is a very React-oriented story; why not compare how working with the
two feels like?

It also feels like the author is primarily interested in client-side
ClojureScript, in which case the Leiningen start-up time should really only be
a problem once per...day? week? I re-start my Clojure(Script) REPL process
only when I change underlying dependencies, which isn't frequent enough for it
to be a major issue.

The biggest issue for me that I agree with is the immature tooling thing, but
that's been getting a lot better since I also blogged about being frustrated
with ClojureScript (relevant link: blog.venanti.us/clojurescript-blues/). Vim
and the CLJS REPL now work well together, and I've been really impressed by
the direction and velocity of Figwheel as a project.

~~~
jaredly
1) I see om/next attacking the same problems as falcor and relay, and david
nolen makes reference to both of them (as sources of inspiration) in the talks
he's given.

2) it may only hurt once a day/week once you have an established flow going,
but when trying to figure things out & start things up, you restart a lot more
than that. hence the barrier to entry

~~~
venantius
1\. Going to look at the recent state of Om/next docs, I see that you're
right. I don't think the earlier iterations of the project had quite the same
focus but it's clearly been made a higher priority.

2\. I think the barrier to starting a new project is unreasonably high, yes,
and requires a highly inconvenient amount of configuration familiarity.
Unfortunately the gap between just running the ClojureScript compiler on a
single namespace file and actually configuring a viable project and build
pipeline in Leiningen is quite large and really requires a concerted effort to
overcome (or, to have someone nearby who's willing and able to show you what
you're doing wrong).

------
marianoguerra
hi, just published a two parts step by step how to on how to do a om.next end
to end example, you may find it useful:

Om.next end to end - Part I: Backend

[http://marianoguerra.org/posts/omnext-end-to-end-part-i-
back...](http://marianoguerra.org/posts/omnext-end-to-end-part-i-backend.html)

Om.next end to end - Part II: Frontend

[http://marianoguerra.org/posts/omnext-end-to-end-part-ii-
fro...](http://marianoguerra.org/posts/omnext-end-to-end-part-ii-
frontend.html)

~~~
jaredly
looks neat!

------
smrtinsert
I still view the language as a one man hackers sorta thing. I hate setting up
a new project with the options I want, not to mention I always seem to be the
guy submitting corrections for windows machines (come on ppl, really).

While coding it is awesome, debugging and maint is hell. I'm off to Typescript
land after a great two year trip with ClojureScript. It reminded of everything
I loved and hated about a dynamic language.

~~~
eggy
Yes, I am sticking with F# and Typescript. I still love PicoLisp and Shen for
my own projects, and as Lisps. Shen runs on everything, and is very versatile,
but has minimal libraries and community. I find both very readable months
later, but then again I also love the J Programming language!
Clojure/Clojurescript are too convoluted with their purposeful tie-ins to the
JVM/JavaScript. Cleaner Lisps, Common Lisp, are easier for me to deal with
later on when reviewing code I've written, although, I have not written
anything medium to large.

------
nickbauman
What about midje? It reruns the tests every time you save a file, no restart
required. It's completely awesome, which everything were like this.

lein midje :autotest

------
stcredzero
I'm really surprised that there isn't much better debugging support for
languages that use JS as a compiler target. Everyone should be able to simply
debug in their source language. REPL should simply return JS objects and
values, but allow people to type in expressions in whatever language they
have. (Might require the compiler to be written in JS or compiled to JS, then
also add an API.)

~~~
iagooar
Well, it all starts with JS not having the best stacktraces (although they
have gotten a lot better in the last years).

------
MikeOfAu
I've used clojurescript commercially for a couple of years. It has been a good
experience.

More than anything it has completely changed my world view (and I'm a very
experienced, older programmer who has seen a bit). I feel very lucky to have
had this opportunity.

IMO, some of the issues you raise are genuine, some not.

For example, the JVM startup time issue is never, ever a problem. If it is,
you aren't using the tools right.

I use Cursive and figwheel etc, so I find the tooling generally fine and in
many ways excellent. The trajectory in this area is good.

Debugging initially can be rough. Knowing about things like cljs-devtools can
dramatically improve things. But, yeah, valid point.

And, yes, poor error messages can definitely be a problem initially --
although this has improved over the last year.

To get going, I'd recommend you use this set of technologies:

\- use Cursive/InteliiJ
[https://cursiveclojure.com/](https://cursiveclojure.com/)

\- use reagent, rather than om. [http://reagent-
project.github.io/](http://reagent-project.github.io/)

\- use figwheel

\- use cljs-devtools with Canary for debugging

\- use Schema to provide faint typing -
[https://github.com/Prismatic/schema](https://github.com/Prismatic/schema)

\- perhaps use clairvoyant for debugging
[https://github.com/spellhouse/clairvoyant](https://github.com/spellhouse/clairvoyant)

\- use timbre for logging
[https://github.com/ptaoussanis/timbre](https://github.com/ptaoussanis/timbre)

\- use re-frame [https://github.com/Day8/re-frame](https://github.com/Day8/re-
frame) (if the app is slightly more complex) <\--- warning I'm biased

\- perhaps use re-com - [https://github.com/Day8/re-
com](https://github.com/Day8/re-com) <\--- warning I'm biased

\- you may also be interested in the head start provided by
[http://www.luminusweb.net/](http://www.luminusweb.net/) for client/server

-

Perhaps just start here: [https://github.com/Day8/re-frame-
template](https://github.com/Day8/re-frame-template) and work out. (I'm
biased)

Good luck.

~~~
jaredly
lots to look into, thanks!

------
lgas
The post says:

    
    
      In javascript, everything is mutable, but w/ new es7
      spread/rest syntax it is increasingly easy to just do
      immutable anyway. E.g. instead of myobj.x = newx you can
      do myobj = {...myobj, x: newx} and everything is immutable
      & persistant!
    

But if I'm reading this right:

[https://github.com/sebmarkbage/ecmascript-rest-
spread](https://github.com/sebmarkbage/ecmascript-rest-spread)

They will be neither immutable nor persistent.

~~~
jaredly
right. should have "(by convention)" in there. unfortunately not (yet)
language enforced.

~~~
lgas
Ah. Guess that makes sense. I'm lucky enough to be able to use ClojureScript
so I guess I've fallen behind on modern JS.

------
andrewchambers
Clojure startup time is less of an issue with clojurescript. The idea is is
you start the compiler and run it in watch mode.

------
erichmond
I think most of your issues really come down to not embracing or understanding
a proper clojure(script) workflow and/or not really understanding the tooling
that currently exists.

I double checked the date of this article to make sure this wasn't written 6
months ago and posted now.

You should check out the clojurians slack channel, there you can probably get
good answers for 85% of the things that are holding you back.

Good luck with it, using clojure/script + cursive clojure + intellij has been
the best development experience I've had in 18 years of professional coding!
It's 110% worth the investment.

~~~
jaredly
thanks! Yeah, I'm really excited about clojurescript, but there is a big
barrier to get over. I'm working on it, and hope to report back :)

~~~
dustingetz
I may have accidentally downvoted you on mobile sorry

------
auvrw
i just dove into clj & cljs w/o such a cost-benefit analysis b/c after writing
some scheme and elisp, it seemed like it would be fun, maybe more fun than js,
and for the most part, it has been.

good article overall. a point that was a little irksome was

> chrome devtools is way ahead of your cli repl (and even your editor-
> integrated repl) in _a bunch of_ important ways

(emphasis added). b/c while i'm not saying the devtools is not ahead of
figwheel+cider in some sense, enumerating specific want-to-haves would be more
informative.

my main nice-to-have (and maybe there's something out there???) would be a way
to set breakpoints for dropping into a repl. b/c of the scarcity of mutable
state, it hasn't been such a problem, but there have been one of two times
where i could've saved a few minutes by throwing a `(debugger)` or something
in.

