Hello and welcome to ClojureScript (CLJS)! It is a new language for front-end web development (i.e. a language that compiles to Javascript for use in the browser).
CLJS is fundamentally different from Javascript and other compile-to-JS languages like Dart, CoffeeScript, and LiveScript. It uses a more powerful yet simpler syntax, it employs useful defaults to combat the "new spaghetti code" that is mutatable stateful objects, and it supports a lot of UI data-binding patterns at a native language level.
Leiningen is the command-line tool used for building ClojureScript projects.
- Install JDK (if you haven't already).
- Install Leiningen.
If you want to setup Sublime Text Editor to highlight ClojureScript files,
open any file with a .cljs
extension in Sublime, then select:
View > Syntax > Open all with current extension as... > Clojure
There is literal data:
; number
1.23
; string
"foo"
; keyword (like strings, but used as map keys)
:foo
; vector (array)
[:bar 3.14 "hello"]
; map (associative array)
{:msg "hello" :pi 3.14 :primes [2 3 5 7 11 13]}
; set (distinct elements)
#{:bar 3.14 "hello"}
And there is symbolic data:
; symbol (represents a named value)
foo
; list (represents a "call")
(foo :bar 3.14)
ClojureScript can evaluate data to create a new "value" from it.
-
Literal data evaluates to itself, of course:
1.23 ; => 1.23 "foo" ; => "foo" [:bar 3.14 "hello"] ; => [:bar 3.14 "hello"]
-
A symbol evaluates to the value bound to it:
foo ; => 3
-
A list evaluates to the return value of a "call".
(+ 1 2 3) ; => 6 (= 1 2) ; => false (if true "y" "n") ; => "y"
If the first element of a list is a function, then the rest of the elements are evaluated and passed to it.
; String concatenation
(str "Hello" "World")
; Arithmetic
(= a b) ; equality (true or false)
(+ a b) ; sum
(- a b) ; difference
(* a b c) ; product
(< a b c) ; true if a < b < c
; Evaluation Steps
(+ k (* 2 4)) ; assume k evalutes to 3
(+ 3 (* 2 4)) ; (* 2 4) evaluates to 8
(+ 3 8) ; (+ 3 8) evalutes to 11
11
If the first element of a list is one of 16 special forms, then the rest of the elements are passed to it unevaluated.
(if (= a b c) ; <-- determines if a=b=c
(foo 1) ; <-- only evaluated if true
(bar 2) ; <-- only evaluated if false
)
; define k as 3
(def k 3) ; <-- notice that k is not evaluated here
; (def needs the symbol k, not its value)
; make a greeting function
(fn [username] ; <-- expected parameters vector
(str "Hello " username))
; oops, give the function a name
(def greet (fn [username]
(str "Hello " username)))
(greet "Bob") ; => "Hello Bob"
If the first element of a list is a macro, then the rest of the elements are passed to it unevaluated, but the value returned by a macro evaluated. Let's illustrate that difference:
This difference in evaluation allows macros to act like code-generating
functions. For example, the defn
macro expands to def
and fn
, as we used
separately in a previous example:
; create a named function using the defn macro
(defn greet [username]
(str "Hello " username))
; the definition for the defn macro (over-simplified)
(defmacro defn [name args body]
`(def ~name (fn ~args ~body)))
App developers rarely need to create their own macros, but it is an indispensible tool for the library developer to give app developers the full flexibility of the language.
Here are the resources and steps that I took while learning ClojureScript. (Most resources covering Clojure also apply to ClojureScript, since they share a significant subset with each other.)
- Reading the book ClojureScript Up and Running
- Reading the book Clojure Programming
- Doing ClojureScript Koans
- Reading ClojureScript Style Guide
- Reading Clojure Programming By Example
- Reading Clojure Functional Programming
- Thumbing through Clojure Core API
- Reading ClojureScript - Differences from Clojure - Host Interop for accessing javascript properties like
(.-Infinity js/window)
and functions like(.sqrt js/Math 25)
. - Reading Javascript to ClojureScript synonyms
- Experimenting in
lein repl
for Clojure REPL. - Experimenting in http://clojurescript.net/ for ClojureScript REPL with a browser context.
- Reading docstrings of functions I encounter with
(doc <funcname>)
in REPL. - Miscellaneous ClojureScript things to know