Skip to main content

ClojureScript

ClojureScript is a robust, practical, and fast programming language with a set of useful features that together form a simple, coherent, and powerful tool.

ClojureScript is a compiler for Clojure that targets JavaScript.
In LiveCodes, it runs in the browser using the official ClojureScript compiler, self-hosted in the compiler worker. The compiler is provided by the @live-codes/cljs-selfhosted-compiler package.

Note

The clojurescript, cljs, clj, cljc, edn and clojure aliases currently use the Cherry-based ClojureScript compiler and will switch to this self-hosted compiler in the future. Use the clojurescript-cherry alias to keep using Cherry.

Language Info​

Name​

clojurescript-selfhosted

Aliases​

clojurescript, cljs-selfhosted, cljs, clj, cljc, edn, clojure

Editor​

script

Compiler​

The official ClojureScript compiler, self-hosted in the compiler worker.

Version​

@live-codes/cljs-selfhosted-compiler: v0.3.0

Usage​

LiveCodes compiles ClojureScript to JavaScript in the browser using the official compiler, self-hosted in the compiler worker. This provides real cljs.core semantics and real analyzer diagnostics.

(:require ...) can resolve the namespaces that are bundled with the compiler:

  • cljs.core
  • clojure.string
  • clojure.set
  • clojure.walk
  • clojure.edn
  • cljs.pprint
  • clojure.core.reducers
  • clojure.core.protocols
  • clojure.data
  • clojure.zip
  • clojure.datafy
  • cljs.math
  • cljs.proxy
  • cljs.stacktrace
  • cljs.test

Three reader namespaces are also require-able, because they are already present in the page runtime:

  • cljs.reader
  • cljs.tools.reader
  • cljs.tools.reader.edn

They (and the cljs.tools.reader.reader-types and cljs.tools.reader.impl.* namespaces under them) are already present in the page runtime because clojure.edn pulls them in transitively, so they cost nothing extra; they are listed here because they are require-able and work.

defmacro works and is evaluated at compile time. Source maps are on by default.

cljs.test's macros expand in the compiler worker like any other macro. deftest, is, testing and run-tests come from its cljs/test.cljc macros half, and are expands through clojure.template, which is served to the worker next to it. The compiled test file is page JavaScript that calls cljs.test's runtime (cljs/test.cljs), which the page provides alongside the other bundled namespaces.

This example demonstrates usage and JavaScript interoperability:

show code
import { createPlayground } from 'livecodes';

const options = {
"config": {
"activeEditor": "script",
"markup": {
"language": "html",
"content": "<div class=\"container\">\n <h1>Hello, <span id=\"title\">World</span>!</h1>\n <p>You clicked <span id=\"counter\">0</span> times.</p>\n <button id=\"counter-button\">Click me</button>\n</div>\n"
},
"style": {
"language": "css",
"content": ".container,\n.container button {\n text-align: center;\n font: 1em sans-serif;\n}\n"
},
"script": {
"language": "clojurescript-selfhosted",
"content": "(ns demo)\n\n(def title \"ClojureScript\")\n\n(set! (.-innerText (js/document.querySelector \"#title\")) title)\n\n(def counter (atom 0))\n\n;; you can use JS interop to wire up DOM events\n(.addEventListener\n (js/document.querySelector \"#counter-button\")\n \"click\"\n (fn [_]\n (swap! counter inc)\n (set! (.-innerText (js/document.querySelector \"#counter\")) (str @counter))))\n\n;; check console\n(js/console.log (str \"Hello, \" title \"!\"))\n"
}
}
};
createPlayground('#container', options);

npm Imports​

npm packages are not supported, unlike the Cherry-based ClojureScript, which imports npm packages as ES modules. For example, (:require ["react" :as React]) fails with No such namespace. Use the Cherry-based ClojureScript for npm-dependent code.

Starter Template​

https://livecodes.io/?template=clojurescript-selfhosted