ClojureScript: Things That Might Worry You, but Shouldn't (2012)
jasonrudolph.com
jasonrudolph.com
I think the arrival of core.async makes ClojureScript an even more compelling option as it has the potential to eliminate an incredible amount of incidental complexity.
Thus far, everyone I've taught Clojure concepts to really appreciates the functional bend of the language, immutable values, and of course the elegant sequence/collection abstractions/persistant data structures that Clojure provides. But semantics are almost never a convincing argument (for most for programmers I know) for spending the time to pick up another language.
What really pushes people over the edge in my experience from thinking of Clojure as "just another Lisp" or a parentheses laden toy, are the amazing concurrency primitives that Clojure provides out of the box. Once my colleagues realize how trivial (and fun!) both concurrent and parallel computation becomes with Clojure, they're hooked and want to dive in.
The talk you gave is probably the most concise manifesto I've yet to come across of just how much better Clojure's semantics are for, well, pretty much any complex problem I can think of. You did an absolutely fantastic job with your assemblage of example functions which definitely shows off the language.
But I know that if I want to convince the company I work at to adopt ClojureScript as a JS replacement for our client side applications, an argument for superior semantics is almost never going to get very far.
Clojure (in combination with libraries like Incanter, JVM interop, etc.) allows me to completely replace R & Python for both exploratory data analysis, machine learning, and building a powerful backend for any distributed application with a double whammy of awesome - I get a much better language for expressing a lot of ideas AND it's fast as hell. I can scale my Clojure code to a cluster of CPUs for training some model without a second thought. I can write really powerful software and never feel limited in what I can accomplish and in the end, project managers/execs just can't argue. Simply nothing else exists in this class with this combination of agility, functional elegance, and "enterprise" class power.
Okay, this comment began as a thank you for making a great appeal for ClojureScript and has unexpectedly turned into... I'm not even sure.
So, TLDR? We need a killer feature that goes beyond semantics for ClojureScript that fixes something broken and practical in JavaScript. Is this a seamless and powerful Web Workers VM or abstraction that just works? Is it a mature core.async in tandem with full featured promises? Is it a new core lib that makes having to think about client/server interaction a problem of the past? I just don't know.
Of the things that you mentioned, I'd wager that core.async will be the captivating feature for ClojureScript. David Nolen's excitement is a good gauge. If that increases adoption significantly, it's my hope that ClojureScript's other benefits keep the fire burning.
One is the port of core.logic. AFAIK there is not a comparable Javascript logic library, although the ClojureScript port does not have all the features of the Clojure base.
Another novel feature is integration with nrepl via the piggieback library[1]. This allows you to evaluate ClojureScript code directly in your running web app if your editor has nrepl connectivity. Again, I don't know of a way to do this with current Javascript tools. But here again, the solution still feels like it lacks maturity.
I don't understand enough of core.async to really comment, but the excitement around it seems to point to another rather exclusive bit of ClojureScript functionality.
The two easiest ways to think of FRP are to either a) imagine it as declarative data binding with the ability to add function transformations or b) think of Excel cells and their functions and dependencies.
Pedestal [1] seems to be an attempt at getting there but it's still incredibly convoluted compared to its Common Lisp equivalent Cells [2]
[1] http://pedestal.io [2] http://common-lisp.net/project/cells/
P.S. If you combine FRP with Clojure's purely functional data structures you also get an amazing 'replay' feature since your UI is nothing more than your (client + server) data models materialized into a view through a graph of FRP functions.
1) there's no source maps. IE: a browser stack trace does not map exactly to your clojurescript code so it can make things hard to debug.
2) finding and fixing performance issues in your clojurescript would be very challenging, especially if you're not an expert in javascript already (which I'm not)
I took their advice but a personal issue I had along the way was, where the hell is the "hello world" getting started guide!? I was never able to find documentation that said, "write this simple file and type this simple command and now you've just built your first clojurescript example". Keep in mind I cut my research short, but I did put at least 2 hours into it.
So I decided to use coffeescript instead. I think it's closer to the raw javascript but it's more concise. I haven't had any performance issues and even though coffeescript is supposed to have source maps, I haven't needed to use them yet.
It's giving me confidence to try clojurescript for my next project. I think it'll be an even better experience than coffeescript. The ability to write your program in one language, front and backend, is really appealing.
This is a fantastic tutorial - http://github.com/magomimmo/modern-cljs
RE: performance. I don't know who you talked to, but they are misinformed we spend a ridiculous amount of time on performance. It's certainly possible to do an HTML 5 canvas game in ClojureScript - http://swannodette.github.io/2013/06/10/porting-notchs-minec.... It is true that if you want to do a computationally intensive game you need to know something about JavaScript performance - but that's to be expected.
Yeah I feel comfortable trying clojurescript next time. Thanks for the info.
For example, right now I'm toying around with a declarative syntax for specifying arbitrarily complex mesh animations in terms of partial functions. To illustrate, instead of having a render loop where conceptually you are modifying something globally in a once per frame, iterative fashion, instead you would feed your rendering context a hash-map that both specifies animatables to be animated, and applies these partial functions onto the specified properties of the animatable object.
Trivial example: {:animatable some-planet :animation {:rotation {:y (partial + rotation-speed) } } }
Anyway, I suppose my advice is to not give up on using ClojureScript here because the potential for making the development of your game a thoroughly enjoyable experience is, for one, a huge win. Aren't we supposed to be enjoying this stuff at the end of the day?
Take advantage of the language and be creative. I have never run into a situation where ClojureScript has somehow bottlenecked performance in any way, and I honestly can't really imagine that being a real concern. This is doubly true in a WebGL graphical context where most of the potentially awesome looking stuff (www.shadertoy.com) is being offloaded to the GPU and has absolutely nothing to do with Javascript or ClojureScript.
My last piece of advice: figure out how often you want to deal with native javascript objects instead of Clojure data structures early on, and stick to it as a convention. The little differences in how the language treats the two (in a collection/sequence sense) will drive you (or me) crazy. I personally prefer to take any JS object I'm going to make considerable use of and turn it into a full fledged Clojure object until I'm finished with it. Obviously this advice doesn't apply to short lived objects, or simple method calls.
However, for folks who just want to give cljs a try, lein-cljsbuild does make it pretty easy at this point. Once you have lein and the lein-cljsbuild plug-in installed, the basic information on how to get a project up and running is here:
https://github.com/emezeske/lein-cljsbuild#just-give-me-a-da...
They also include example projects in the lein-cljsbuild repo that make use of some of the popular clojure web libraries like ring and compojure:
https://github.com/emezeske/lein-cljsbuild/tree/master/examp...
And yes, we need Closure advanced compiled mode when ClojureScript ships with a standard library nearly 7500 lines long.
Also note that the most popular JS libraries like Underscore.js and jQuery add little value to ClojureScript given the rich standard library and pure ClojureScript solutions like Domina.
Integrating with functional frameworks like Angular.js isn't too painful as evidenced by Weathertron - http://keminglabs.com/blog/angular-cljs-weather-app/
but if clojurescript could make this kind of "hacks" integrated: i.e allow (:use [js/Foreign_lib :only lib.method]) instead of externs.js, then it will be way easier to attract newcomers.
I agree that using google closure will save a lot of work, for now. But I also think that clojure guys should come up with their own(and better) compiler that has awesome compiled asm.js code as killer feature.