Podcast that inspired comparison of CLJS to Scala.js/Slinky


I enjoyed this podcast focusing upon a fellow JVM language. I was distraught to learn that CLJS+Reagent isn’t such a unique snowflake in its approach to wrapping React and providing things like the Figwheel experience and sharing front-back code (which I used to think was only possible with cljc). To be fair, CLJS never actually claimed to be as special as I liked to imagine it was. He also spoke of “fluid typing” for his Scala and Haskell, which sounded identical to our “gradual typing” and spec.

So, as someone who really loves Clojure[script], what are its unique and almost-unique propositions? It sounds like Scala.js might actually be ahead of it in terms of sharing code and leveraging the eco-system.

Some that come to mind as possibilities:

  • Google Closure, esp. dead-code elimination.
  • Immutable data structures by default
  • REPL (no idea if this is a thing with Scala)
  • Macros (I don’t use them much, but I know I could)
  • Dynamic typing (hotly contested as an advantage, but I assume we at this forum see it as a pro)
  • Lisp syntax (same as dynamic typing: take it or leave it as a pro, but I’ll take it)

What would you add, particularly if you know something about Scala work?

Hi there! Scala.js author and lead maintainer here. I saw this on Twitter, and I’ll just answer with some facts about Scala.js.

Scala.js also uses Google Closure automatically in production builds. We use it in a different way than CLJS, though: CLJS chooses to interact particularly well with Closure-aware libraries, which allows to dead code eliminate across the JS libraries and the CLJS code. However, it means that for some JS libs that are not designed for Closure, additional externs and exports annotations may be necessary to preserve semantics. In Scala.js, we want to guarantee semantics at all cost, and don’t require users to add any annotation. However that means that we only let Closure run on our code, and not across JS dependencies.

Scala also uses immutable data structures by default.

Scala for the JVM has a very good REPL. However, there is no REPL in Scala.js, because of technical difficulties linked to core design choices (there are tradeoffs at play here).

CLJS is clearly ahead of us here.

Also available in Scala/JVM and Scala.js.

Of course Scala favors static typing, and Scala users typically assume static typing is an advantage. Nevertheless, sometimes interoperability with JavaScript–although usually statically typed in Scala.js–calls for a bit if dynamism. That’s why we have a js.Dynamic type.

Cheers everyone, I love that CLJS exists and gives us such hard yet friendly competition :smile:


Going to be hard to answer this without devolving into a language war, but I’ll try :beers:

In my opinion, what makes Clojure unique is the intersection of all its features, and the conscious choice to omit certain features as well. And I feel this is true for most languages, you need to consider the sum of all its part.

So what’s unique about Clojure in my opinion is that it has all at ounce:

  • An homoiconic syntax where code is data, and data is code
  • Which is clear, consistent, concise and enables full structural editing
  • Which can be extended with new semantics through macros trivialy
  • Where data is a first class citizen, and at the center of everything
  • In that it comes with a full suite of immutable persistent collections like map, lists, vectors, sets, sorted sets, queues, stacks, etc.
  • And those all support heterogeneous data, because the world is such
  • And they are the basic holder of data that all other function operate over so that data can be very easily manipulated
  • And where equality of data is inherent and automatic
  • Where functional programming is the dominant paradigm
  • And meta-programming the second most common paradigm
  • Yet the good parts of Alan Kay style OO are first class (late binding and polymorphic dispatch)
  • And even still Java style OO can be used where it is actually the best for the task, i.e., to build language constructs like data-structures, where encapsulation is a must
  • With pretty darn good support for Logic programming as well
  • Yet where using the wrong paradigm for a given task is made purposely more painful, to drive correct choice of paradigm for given problem
  • Which is fast and efficient, able to handle modern workloads competitively
  • Fully dynamic, where every aspect of a program can be modified and modify itself at runtime
  • Targeting existing platforms such as JVM, CLR, and JS
  • With first class interop
  • That doesn’t try to reinvent the wheel, using each platform for what it is good at.
  • With a small enough core, that the community can extend its reach to new hosts: Joker, Clojerl, Ferret, etc.
  • With full support for multi-threaded and multi-core programming
  • Designed for concurrency
  • But offers a selection of concurrent paradigm: CSP, Executor, Future, Locks
  • With an amazing REPL
  • Smartly avoiding having inheritance, reader macros, static types, custom data containers, implicits, etc.
  • And a great community!

It isn’t anyone of those that in my opinion make Clojure my favorite language yet, but the sum of all these things and some more I mostly forgot.

1 Like

@sjrd The main differences between Clojure and Scala are:

  • Scala is a traditional FP, and Clojure is a FP based on RMDB theory. Therefore Clojure is more suitable for processing data.
               Clojure -> DBMS, Super Foxpro
                   STM -> Transaction,MVCC
Persistent Collections -> db, table, col
              hash-map -> indexed data
                 Watch -> trigger, log
                  Spec -> constraint
              Core API -> SQL, Built-in function
              function -> Stored Procedure
             Meta Data -> System Table

Note: In the latest spec2, spec is more like RMDB.

  • Clojure is Lisp dialect, simpler.

  • Clojure is more suitable for data flow programming and Warehouse/Workshop Model. It systematically simulates integrated circuit systems and large industrial production lines. In the computer field, for the first time, it was realized that the unification of hardware engineering and software engineering on the logical model. It has been extended from Lisp language-level code and data unification to system engineering-level software and hardware unification. and it brings large industrial production theory and methods to software engineering. It incorporates IT industry into modern large industrial production systems, This is an epoch-making innovative theory and method.

This is the Pure Function Pipeline Data Flow v3.0 with Warehouse/Workshop Model.


Honored to have you here and your comments on Scala.JS. Thanks!

I haven’t dug into the history yet, but did cljs (e.g. David Nolan’s work) precede or follow scala.js? After your comment about friendly competition, I’m very curious to know in what ways the languages have influenced each other. Also, what is scala.js reason for using Closure if not deadcode elimination?


ClosureScript preceded Scala.js by a year or so, IIRC. There hasn’t been much direct inspiration–in fact major technical decisions are diametrically opposed between the two systems–but it’s always been good to check up on what works better on the other side, so that we know what we could do better. Live reloading is a major example where we’re jealous of CLJS, and where I’d like us to do better.

We use Closure mostly for its advanced minification of symbols across the codebase and JavaScript-specific optimizations for size. Prior to giving code to Closure, we apply our own dead code elimination and optimizations, which take advantage of the static types. Our dead code elimination, per se, is better than Closure’s, because of the reliable types. We can also do advanced optimizations like closure elimination and a form of stack allocation. One example I recall impressed David Nolan was the performance of our 64-bit integers (Longs), which we can achieve because of those optimizations.