Hacker News new | past | comments | ask | show | jobs | submit login
Bringing functional to the frontend – Clojure and ClojureScript for the web (getprismatic.com)
120 points by aria on Jan 17, 2013 | hide | past | favorite | 60 comments



If you're interested in a functional approach to UI code, check out functional reactive programming (FRP). It's a declarative way to specify UI logic which abstracts away much of the inherent messiness of using mutable state and callbacks.

I've played around with FRP in Haskell, and have found it much nicer than the more standard approaches to implementing UI logic. Before using FRP, my main UI experience was with Java Swing and web development, and FRP is definitely a step up. I've found it easier to write the code in the first place and then much easier to add new features and logic.

I've only used FRP with native UIs, but I think it would be very natural for web development as well. It's certainly a shift in philosophy and mindset, but one that I think is well worth overcoming.

Unfortunately, I do not know of a good tutorial for using FRP. I'm sure there are some out there, but I basically picked it up by reading academic papers which are not to everyone's taste. That said, I actually found some of the papers were clearer than the blog posts and SO questions I found online!

I'm probably going to write a basic FRP tutorial in Haskell some time soon, probably built around some very simple application (maybe John Conway's Game of Life). It really is a fun subject. Is anybody interested in something like that?


I recently finally understood FRP and I'm working on my own library on top of Flapjax and Enfocus (ClojureScript) to make things simpler than doing everything by hand.

However, I can't find examples of systems of moderate (or big) size - nothing to get inspiration from, all examples I've seen are quite small and do too much by hand. They often select elements (like button to track click on) from whole document by id (and in big app this is pretty useless except for some top-level elements), or interwind templates with bindings to events and interaction between them is structured so that it feels like almost using globals. Directly changing top-level data from some inner template.

Anyway, I've got some ideas - display is easy though, what's hard is nicely structuring forms and buttons IMO - but it takes time to carve them out in code. I would love to read something on topic of structuring applications, which are more than a single input and a single list.


Definitely interested. I've been looking at FRP for a school project. I haven't done a lot of investigation yet, mainly just branching off http://www.haskell.org/haskellwiki/Functional_Reactive_Progr..., saving bookmarks and reading papers like you mentioned.


I also believe that web development doesn't really benefit from functional programming. That said there are two good FRP projects out there:

Elm: http://elm-lang.org/ and to some extent Meteor: http://docs.meteor.com/#reactivity


We use ClojureScript (and Clojure) at http://economi.co and I'm really enjoying it.

Maybe one of the most difficult things coming into it is trying to relate it to something like BackBone.

However generally speaking in Clojure the culture is more about libraries than frameworks.

C2 http://keminglabs.com/c2/ which on the outset looks just like a ClojureScript version of d3 is actually a great library to use instead of a traditional front end framework.

Check the example implementation of the class TodoMVC list here: https://github.com/lynaghk/todoFRP/tree/master/todo/c2

It's uses normal Clojure data structures within atoms as the data model (https://github.com/lynaghk/todoFRP/blob/master/todo/c2/src/c...) and uses C2 to automatically update the UI (https://github.com/lynaghk/todoFRP/blob/master/todo/c2/src/c...). Very elegant.

I'm just starting to explore this area myself, but have already found it useful for a few smaller parts of our site.


Don't worry about how anything compares to frameworks, because they don't matter anymore.

We think traditional frontend frameworks - whether of the rails/django variety or the backbone variety, are generally rubbish in a nearly infinite number of ways. It's a style of programming based on wrapping weak mutation oriented idioms behind monolithic APIs and design patterns. We think default functional style and fine grained composability is the future, and mutation + oo design patterns + frameworks is the past.


It may be the future for very skilled developers that have already familiarised themselves with frameworks and design patterns and are capable of moving past them. The majority of software developers benefit enormously from the conventions encouraged in a framework like Rails. If Clojure is going to be adopted widely (if that is a goal of the project at all), the community needs to work on better communicating best practices to make up for the lack of framework 'guidance'.


Eh, even the least charitable would have to admit that frameworks enforce style. On a large project, this matters hugely. I don't care how good your devs are they DO have different opinions re: style.


I disagree -- frameworks enforce structure (especially of callbacks), not code style.

Unity of code style is something you can solve with standards, style guides, pairing with new developers, and following conventions from surrounding code.

Clojure is nice because the community, while having different opinions about how often you should use X technique vs Y, generally has core sensibilities about what makes for good, simple code that composes well and doesn't tangle concerns. (This is largely due to the influence of Rich Hickey.) This (and not "perfectly uniform code style") makes for an effective large team.


I'm new to programming and I want to start off on the right foot. I'd love to learn more about the differences. Where should I look?


We did a post a while back on the frameworks vs. libraries and our overall take on software engineering:http://blog.getprismatic.com/blog/2012/4/5/software-engineer...


Thank you!


> generally rubbish in a nearly infinite number of ways

What?


If you're interested in learning more about Clojure and ClojureScript, check out the upcoming Clojure/West conference in Portland, OR March 18-20th (http://clojurewest.org/schedule), including a keynote from Rich Hickey, creator of Clojure. There is also a 1 day training class the day before on ClojureScript if you want the deep dive (http://clojurewest.org/training). Register here: http://regonline.com/clojurewest2013


Highly recommended! Alex's events are always great - long on technical and short on BS!


Great article. I have spent a fair amount of time playing with ClojureScript, read "ClojureScript: Up and Running" and a lot of tutorial material on the web, and used it a bit in a customer project.

That said, ClojureScript has not really clicked for me yet, but this article and the pointer to dommy is getting me closer to adopting ClojureScript.

I use Clojure + Compojure (and still Noir) + Hiccup for just about all of my web app development. Love Hiccup. Having (mostly) Hiccup on the client side with dommy looks very cool.


I'd be curious to hear what you're not liking about it.


It is not that I don't like it, I just tend to be a little slow in adopting new stuff into my set of almost always used tools.


So guys, I hate to bring this up in an unrelated topic, but when are you going to open-source Graph? It has been 4 months since you said "soon" and I'm squirming in anticipation.


On server-side templating - did you consider a selector-based approach like cgrand's Enlive?

As I see it, it brings the best of both worlds (the comprehensibility of "logicful" templating, the maintainability of strictly separating presentation and data transformations)


No, but I think enlive is great.

To me and the team, most of our functions are making Clojure data structures and thinking of templating as converting data to dom elements or HTML strings seems the most compatible with that way of thinking. But both are definitely valid.


"The above is valid Clojure code, not another language whose syntax you have to learn or separate compiler to use."

Even though this is a fair point, the comparison between the Jade solution and the Clojure one is invalid. Jade was conceived as a whitespace-significant language. Its biggest benefit over plain HTML (or HTML-based template engines like Moustache) is the usage of indentation to determine hierarchies.

The comparison would be more valid with something like http://domo-js.com, which is solving the exact same problem: using a single language (JS) for markup production – and even replacing CSS.


That's a fair point. Really, I think we're making the argument that we prefer data approach to templates (i.e., language-native data structures (maps, arrays, strings)) represent html structure.

You can certainly take that approach in JS. domo-js isn't quite that, it would look more like:

["html" ["head" ["title" {class: "class1"} "Welcome to Domo"]]]

As we say in the post, you can totally pull all this off in JS, but I think if you're going to be manipulating nested data structures, it's better to have immutable data structures built in and the suite of functions that can manipulate them. Clojure makes building template structures really easy: persistent data structures, map/seq argument destructuring, keywords, sets, etc.


It is not clear that whitespace sensitivity has ever been a good idea in any language. In jade, it is often just encourages the antipattern of hardcoded hierarchy and throwaway templates rather than reusable abstraction. We like actual abstraction more than trivial syntactic suger.


I really love Clojure, but it still feels a bit heavy-weight for anything but numerical computation. However, I'd ignore that if the performance gains were significant. What are the performance advantages of ClojureScript server-side templating compared to client-side Javascript templating? The vogue style these days seems to be a one-page app where the clicks take barely any time, because the jQuery/Zeppo/Underscore selectors are all cached.


While you can use ClojureScript (CLJS) server-side running on say node.js, the largest benefit is as a replacement for client-side JS (ClojureScript converts to JS at compile-time).

You can actually use all the libraries you mentioned (jQuery, underscore) from ClojureScript. What CLJS really brings to the table are a set of abstractions and data structures that make it easier to write strong reusable functional code. In fact, alot of underscore comes built into CLJS and I think much of what jQuery buys you can be handled as a good CLJS library (but more on that soon!)


The idea of decomposing jQuery into small libraries Clojure-style is very appealing. The advantage would be building the specific Javascript file needed by the client at request time, and caching intelligently to prevent doing this too much. The extra benefit would be, you could break out the pieces of jQuery devoted to patching cross-browser issues, and only include the ones you really cared about.

Very cool!


Yeah absolutely. One of the better CLJS features is getting the Google Closure modules and explicit dependencies.

We'll probably add dom selectors and/or manipulation and wheter it's the same library as dommy (github.com/prismatic/dommy) or a different one will depend on if the selectors borrow the same abstractions and syntax as templating.


"I really love Clojure, but it still feels a bit heavy-weight for anything but numerical computation."

That is really weird. If there's one area where Clojure feels a bit strange to me it is numerical computation. I haven't fully looked into it yet but there's the whole underlying Java idiosynchrasies issue : for example where you need to wrap inside unchecked-int to dodge overflow issue or the fact that you need to be careful to be sure to fall back to primitives if you don't want to kill your perfs, etc.

In addition to that a lot of intensive computation do work really best when using mutable data structure. Which is sharp contrast with Clojure's main philosophy that favors avoiding mutability. Note that it cannot be done, it can, but it kinda feels "weird".

Then your question gets weirder: you ask about the advantages of ClojureScript server-side templating when the article specifically mentions using Clojure on the server and ClojureScript on the front-end (if I'm not mistaken).


Actually, we do our numerical work in clojure too and make heavy use of mutable java data structures - and it's a joy to program in Clojure for these tasks.


I'm using my ported version of Hiccup [1] to ClojureScript for a while now and share most of my templates between Clojure on the server, and ClojureScript on the client side with good sucess. It can sometimes get a little bit hairy to share code between the 2 platforms, but I hope something like Common Lisp's feature expressions [2] will make it into Clojure and ClojureScript soon. When this arrives, life will be a lot better ...

Just for fun, I benchmarked my Hiccup port against the other candidates.

Compilation Mode: Whitespace {:crate 7.076333333333333, :jquery 1.4643333333333333, :dommy 2.1186666666666665, :hiccup-str 1.985, :hiccup-node 2.3476666666666666}

Running Hiccup and Dommy in advanced mode get's the time towards unoptimized jQuery.

Compilation Mode: Advanced (Crate and jQuery don't run in advanced mode) {:dommy 1.3436666666666666, :hiccup-str 1.0293333333333334, :hiccup-node 1.3506666666666665}

One thing to note: The original Prismatic tests were building jQuery Nodes and appended them to an UL element. Building strings and appending those to the node speeds the whole thing up a little bit further [3]. In the above benchmark :hiccup-node uses DOM nodes to append to the root, :hiccup-str uses Javascript strings.

I can only agree. Using a Hiccup like template system in Clojure is very nice.

[1] https://github.com/r0man/hiccup/tree/clojurescript [2] http://dev.clojure.org/display/design/Feature+Expressions [3] https://github.com/r0man/dommy/tree/hiccup


Author here. Happy to answer any questions or comments.


What ClojureScript libraries are you using?

What other "regular" JS framework/libs do you use with ClojureScript (thinking about jQuery, Backbone, angular and the likes)?

About dommy, what made you choose DOM vs String generation (knowing the later could be faster in some situations/setups)?

And the last one, did you consider EDN? I'd guess you choose json for obvious performance reasons.


Frankly at the moment, we're not using any external clojurescript libraries; we've tried many, but none quite meet our needs or the style we really like. We're internally phasing out jQuery selectors in favor of some code that we'll be releasing once we know it's battle-hardened and ready.

We don't use an MVC or components type framework, but ideas about how to setup those abstractions are percolating.


I added two more questions while you where writing this reply probably.


Ah sorry, I didn't see. So the decision about DOM elem vs String is one I'm not 100% sure about, but I think the performance difference is at most like a 10-15% difference which wasn't that compelling to us. So I didn't see a strong reason to go one way or the other and the code I believe is cleaner producing nodes rather than Strings, but I easily could be wrong on both counts.

I didn't actually consider EDN. I haven't see enough of a win over JSON to consider it, but that could just be misinformed.


I've been using Clojure for a while now. Do you have any particular recommendations for resources for getting started with ClojureScript? I tried a while back and got really confused.


I haven't used it but here's a 10-part mega tutorial on modern Clojurescript: https://github.com/magomimmo/modern-cljs/


Shameless plug, but I'll do it anyway since it's a direct answer to the question: I'm the (co)author of ClojureScript: Up and Running from O'Reilly.

If anyone wants, email me at the address in my profile and I'll get you a discount code.


http://himera.herokuapp.com/synonym.html from Fogus is also a good starting point to have an overview of how to do things and what is possible. Next stop: modern-cljs as mentioned by pchristensen.


"about a year and a half ago ... a relative absence of development tools for building and debugging apps."

I looked at ClojureScript when it was first released, and came to the exact same conclusion. I'm very interested to know how debugging ClojureScript works out for you. From what I remember, the ClojureScript -> JavaScript step generated some code that could be fairly difficult to follow. Also, in your experience, how well does it integrate with other JavaScript libraries?


I really want to like ClojureScript, particularly since the idea of using the same language all around the app appeals to me, but it's not quite the same language. Have you found this to be a pain in practice? I'm specifically wondering about require-macros and lack of support for ~ and ~@, although I'm also curious if you were bit by any of the other differences between Clojure and ClojureScript.


Indeed it's not the same language. I wasn't bit by the macro differences (which are probably the largest non-interop difference) since I tend not to use macros in my Clojure or ClojureScript code. Macros are going to be different since the macro compile host (JVM) is different than the run host (Javascript VM).

Other than macros and the VM interop (ugh I think (.-length str) is an eye-sore for property acesss), the core of the language is close enough that I Don't think of it 90% of the time.


I'd say that not having "the whole language, all the time" is only (potentially) a pain regarding the development process/experience itself, not the quality of the resulting programs - which is what matters at the end.


In general, I believe people underestimate the importance of development time, as well as ease of training/hiring new programmers - one language is nearly always better as far as both of these things are concerned (unless that language is something like Malbolge).


Why jQuery, when ClojureScript already comes with a framework? It's easy to wrap it by a thin layer if you don't like the API, but then you get working advanced mode and one external dependency less.


I agree that using data as templete is great. This is a typical example of "The value of value"(Rich Hickey's speech).

And I think client side have a bit different requirement compared to server side. At client side, I often need to manipulate specific element instead of root element which crate and dommy return. So I forked crate in order to get a collection of created elements as a hashmap. https://github.com/hozumi/crate-bind This is useful. I will create dommy version of this.


the dom is a mutable data structure and the native (fast) dom apis expose mutable interfaces. so dynamic sites (you know, single page html5 apps doing all sorts of client-side dom manipulation) are either going to be slow, or are going to have an imperative core, which is where you need functional programming the most ;(

maybe HTML6 will have native functional dom manipulation and we can rewrite all our favorite javascript libraries to expose functional interfaces. one can dream.


I'm afraid you're confusing data structures (such as vectors, sets and maps) with the document model object.

Not even in JS the DOM and objects are the same - some properties of the DOM have 'magical behavior' attached.

ClojureScript does not provide any functional interface to the DOM - that would involve a Haskell-like model of programming (monads etc), which Clojure programmers rarely do in practice.


i don't think i'm confusing anything. Clojure programmers love their persistent data structures, and in a browser environment, the most important data structure - the document model object - is not persistent and cannot be made persistent in a performant manner because it is a native api.

there is ongoing research into dom manipulaton in clojurescript - Conrad Barski presented one approach[1] at Conj 2012 where the dom is mirrored in clojurescript data structures, and then 'synced' with the dom - so that way the imperative ickyness is tucked away in the sync method - it remains to be seen if that can be made fast enough until we get a native persistent interface to the dom.

[1] https://github.com/drcode/webfui


Characterizing side-effects as a series of supposedly functional transformations doesn't sound quite alright to me.

That said I'm curious about such an approach.


Modeling side effects as transformations on data is what functional programmers do all day. I'm not talking about monads - simple things like inserting keys into a map and manipulating collections does not rely on side effects in functional languages.


Another option for functional on the front end (and back end) is LiveScript. http://livescript.net/ Many people may not have heard of LiveScript.

I prefer LiveScript for a number of reasons, starting with the fact that I just don't like brackets and parentheses enough to want to use them everywhere.


My biggest problem with ClojureScript is that is very hard to reason about code written in it if you are a beginner.


It's definitely a complicated language to learn since you have to learn the complexity of

(1) Clojure core itself and readjust to functional programming (2) Understand how ClojureScript is translated into JS in order to do interop which will absolutely be necessary for any real project (3) Understand Clojure on the JVM in order to understand/write macros


Semi-related question but...

One of the thing that I love when developing under Emacs is that I can get real-time validation of my XML (eg XHTML) based on, say Relax NG. This even works nicely with multiple-major-mode (eg I can get realtime validation of the XML part, yet see JavaScript as JavaScript inside the same source file).

Now my question: with all these templating libraries like Jade, aren't you losing feature like real-time validation?

And when such a templating library comes out, it means every editor out there as to be modified so that it supports it?

Or is there some kind of a schema that can be used to perform real-time validation + auto-completion?

My point is: I definitely see the point as replacing Jade by Clojure because you can then manipulate your templates as data, which is gorgeous. But I don't see the point of using Jade in the first place...


The nice thing about dommy (github.com/prismatic/dommy) is that emacs doesn't need to be changed at all to use it. It's just clojure and all the highlighting and the emacs major mode work.

Also out of the box, you get a repl to live test and evaluate template functions and data structure. It would only take a few lines of emacs lisp to take a string from the repl and pipe it through XHTML validation.


In terms of performance, wouldn't it be far faster to use strings and turn those into document fragments or setting innerHTML? I've been looking at ways to make crate much faster and it seems that would be the fastest solution by far.


That's the approach Hiccups took, it goes as far as generating most of the html at compile time as well. I didn't run benchmarks but I would guess it is faster than crate in some situations (huge fragments, older browsers etc).

Another plus is nodejs compatibilty (if you care about that, but I guess you might :)).

https://github.com/teropa/hiccups


The Community Edition (free) of IntellJ with the Clojure plugin will help you here: I get immediate error highlighting when editing Hiccup code in my Clojure view files - recommended!

A little off topic, but I have been using Emacs to edit Lisp code since the early 1980s, but IMHO IntellJ with the Clojure plugin is a bit more efficient for writing and reading code.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: