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.
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/
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.)
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...
That's why javascript's flow[1] appeals to me so much, and I'm really interested in core.typed.
About core.typed, just be aware that it comes with its own set of issues[0]. I've been down that road and it wasn't great.
[0] http://blog.circleci.com/why-were-no-longer-using-core-typed...
Actually, it's pretty simple to wrap Javascript functions so that you can call them directly from Elm. See e.g. [0] which is called from Elm here [1].
[0] https://github.com/elm-lang/core/blob/master/src/Native/Colo...
[1] https://github.com/elm-lang/core/blob/master/src/Color.elm
Imagine you subscribe to lots of realtime data sources (e.g. via websocket), that deliver lots of updates to your UI. Then you have a race condition whether you can draw the updates faster than you receive them.
In an eventloop environment like Javascript it could be self-regulating (http/ws stack wouldn't receive new frames until you return from drawing. But it might also be not (because a C++ background thread in your browser receives the messages and queues them until they can be pushed to JS) - then you might get out of memory. But I totally agree that it's an exception for UIs to deal with such scenarios, but it should be normal an a server.
Brandon Bloom's fipp[1] works fine but the Chrome Canary dev tools have support for object formatters. I get reasonable results on .170 just doing a (js/console.log a-map).
I've used Clojure for 2 years - I feel the same way. It's a wonderfull language that exposed me to great ideas and showed me that simple things can be simple but boy does it get nasty when things don't fit the provided primitives and actually start getting complex - the language has no tools to deal with complexity it can't simplify.
Also a - for CLJS from me is that they haven't abstracted out the (do ...) macro from channels (ironic with all those talks harping on how simplicity is about disentangling things). The biggest pain in JS/DOM ecosystem is shitty semantics, poor standard library and callback stacks. ClojureScript fixes first two really well and does a half-assed job at fixing the last - channels are too much overhead for such task (from both performance and conceptual POV - putting a queue in front of every callback is silly in a single threaded model).
I feel like Elm is a language designed to explore an idea not to be practical, this is why I haven't tried using it for anything serious.
TypeScript has potential in theory to bring ES6 + type safety to avoid semantic pitfalls - but in practice it's supposedly biggest strength of leveraging the existing JS ecosystem is also it's greatest weakness in that you're still left there with shitty JS ecosystem with zero consistency, most libraries deal with JS pitfalls in their own unique way which doesn't mesh well with other approaches or with TS, fragmented build, packing, dependency management, module loading tools - all trying to solve the same problem in different and incompatible ways - it's just a pile of junk that wastes more time trying to reuse stuff than it takes to build anything - which is probably why most of it is in the state it is - and very few things are actually maintained so the argument that reinventing something means you need to maintain it yourself is not really convincing.
Dart has a built in package manager, has had tools for dealing with async code for a while now (both async/await and streams), it's familiar to the Java/C# devs but it's surprisingly concise (quite a few nice touches like constructor property-parameter mapping or => getter syntax for tedious stuff), the standard library is great and avoids all the JS pitfalls.
The downside is that you still need JS interop because there's no way around it (for eg. emscripten) - and talking to JS from Dart is still nasty - much more involved than CLJS or TS.
Having used all 3 mentioned for non trivial work I like Dart the most and the new JS interop could make it even better.
The only unpractical part I'd noticed was its perspective on reusing components, as seen in this overview under 'Nesting' [1]. That bit of explicit routing aside, may I ask what dissuaded you from using the language seriously?
[1]: https://gist.github.com/evancz/2b2ba366cae1887fe621#nesting
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]