ThoughtStorms Wiki

See also : ComparingFunctionalLanguages

Quora Answer : How does Racket compare to Clojure?

Jul 25, 2017

Firstly understand that RacketLanguage and ClojureLanguage are both in the Lisp family but were created and developed for very different reasons.

I'd say the most important are these :

Racket is an evolution of Scheme. Scheme was invented largely to create an academically rigorous, "principled" Lisp, built from the ground up from a minimal core, which could be extended in Scheme itself.

Clojure was developed to be a good high-level language with the virtues of Lisp and other FP ideals, which could run well on the Java virtual machine, and play well with the Java ecosystem of tools and libraries in industry and "enterprise" contexts.

So Lisp in general, and in particular, Scheme (including Racket) has the ideal that it's as "self-hosting" ie. built in itself as much as possible. And therefore a fairly self-contained world.

Clojure, trades away that ideal in return for using as much of Java as it needs, and is willing to borrow good ideas from Java and rely on Java libraries and frameworks and, in particular, wants to take advantage of the JVM. (Though now it's also ported to Javascript, it's doing more things itself.)

Racket, in particular, has as its ideal that it is a "programmable programming language". In other words, the ideal for Racket is that it's a platform for creating DSLs (domain specific languages) that are customized for the particular application you are writing. You can create highly custom languages for each module of your application, all will sit on top of the same engine, and they can all talk to each other. Racket puts emphasis on the use of "reader macros", that is, things that allow you to customize the syntax of your DSL. You can have a DSL / Racket dialect which looks like BASIC. Or like a text formatting language. Or is ideal for describing web-servers. Etc.

Clojure, on the hand, takes the opposite view. It deliberately chose to NOT support reader macros (despite them being a standard Lisp feature). On the grounds that they'd fill Clojure-world with inconsistent syntactic variation, which would make it harder for programmers to collaborate.

In a sense, this philosophical distinction between Racket and Clojure is the same as that between Perl and Python. Perl celebrated "there's more than one way to do it" and giving the programmer maximum flexibility to express themself however they preferred. Python, OTOH, came up with the term "pythonic", a simple and canonical way that programs should be expressed that maximizes the ability of programmers to read each others' code and collaborate. In Python-world people will criticise you for not being pythonic, even if the code is otherwise fine, because inconsistency is a sin. In Perl, individualism and diversity is celebrated and no-one thinks its polite to criticise it.

Another way of putting it: Python is the Apple of programming languages. Elegant, beautiful, enforced consistency and constraining. While Perl is the Microsoft : many variations between different vendors, incompatibilities but freedom from oppression.

This distinction is even more pronounced when it comes to Racket and Clojure.

Racket is very free, a "wild-west" where anything can happen. The sense of possibility is exhilarating. But frankly, start looking into some of its libraries and they are ugly. They look ugly. Functions have long, silly names. Similar operations on strings vs. arrays vs. other sequences are inconsistent. Etc. Lots of stuff isn't really finished. Or suitable for particular applications.

Clojure is the opposite. I have to say, I genuinely think that Clojure is the nicest, most well designed language I have ever seen in my life. I love it. And the reason for that is that it seems that Rich Hickey and the team have incredibly good taste. They come up with really well designed libraries and patterns for solving problems, that then become the standard. (There's still variation and multiplicity in third-party frameworks, but things tend to converge on one or two preferred solutions pretty quickly). Clojure is beautiful. It is absolutely beautiful.

BUT, that comes at the cost. There is a "right" way to do Clojure. And, to a lesser extent, that right way is partly constrained by the way that Java ecosystem does things underneath.

Some of the Clojure decisions are really good. While all FP tends to value referential transparency and less mutable state, most Lisps allow mutability in some form. Even Schemes and Racket. Clojure constrains mutable state far more; limiting to four very specific mechanisms. Each of which has very explicit rules with respect to multi-threaded parallelism etc. Clojure is almost as principled on mutable state as "pure" FP languages like Haskell and Erlang.

Another great decision is that all collections are lazy.

Another, part borrowed from Java, is that implementationally, everything is in terms of standard Java interfaces. So all sequences in Clojure are using an ISequencable interface. All dictionary / associative arrays use Java's Map interface. Etc.

This gives Clojure massive consistency. And a coherent and standard way to interact with existing Java libraries and frameworks.

In Racket (and other Schemes) where libraries might have been put together on a more ad-hoc basis, you don't have that kind of consistency and rigour. The string library allows mutable strings. And string processing functions have different names from list processing functions, rather than there being a generic sequence API. (There are now Clojure-inspired generic interfaces in Racket, but they aren't well established and the standard libraries don't necessarily use them.)

Finally, while Racket has a lot of nice libraries and good stuff, it's hard to compete with the whole of the Java ecosystem that Clojure has access to. Clojure has many good libraries of its own. But you can fall back to calling on Java libs and frameworks when you want.

One advantage of Racket for beginners is that it comes with its own IDE. Particularly on Windows, it's easier to install and start playing with that than to set up a Clojure development environment. Once again, though, for professionals, Emacs and Vim have good Clojure modes (integrated with REPLs.)

The ClojureScript story for developing in-browser front-ends is now excellent, with Figwheel for doing more or less "live-coding" of your interface. And Reagent and Om as Clojure libraries that wrap React.js. While there is a Racket to Javascript compilation, I don't think the ecosystem is anything like as mature as ClojureScript's.

Backlinks (2 items)