• This repository has been archived on 18/Dec/2018
  • Stars
    star
    375
  • Rank 114,096 (Top 3 %)
  • Language
  • Created over 10 years ago
  • Updated about 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

cljs syntax is simple

cljs

Translations: ไธญๆ–‡.

If you just wanna try something, check out the interactive tutorial.

Hello, this is my attempt at a very concise guide to ClojureScript's syntax! ClojureScript is a Lisp dialect for front-end web development. It compiles to JavaScript for use in the browser.

ClojureScript is fundamentally different from JavaScript and other compile-to-JS languages like Dart, CoffeeScript, and TypeScript. It uses a more powerful yet simpler syntax. There are other differences not related to syntax, such as default immutability to combat the "new spaghetti code" that is mutatable stateful objects, and sane state management allowing language-level data-binding.

I believe that ClojureScript's largest barrier to entry for beginners is probably the foreign nature of its syntax. I hope to explain it as plainly and succinctly as possible with this guide.

Also, check out Parinfer if you want a simpler way to manage parentheses in ClojureScript.

Syntax

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)

Evaluation

ClojureScript can evaluate data to create a new "value" from it.

  1. Literal data evaluates to itself, of course:

    1.23                 ; => 1.23
    "foo"                ; => "foo"
    [:bar 3.14 "hello"]  ; => [:bar 3.14 "hello"]
  2. A symbol evaluates to the value bound to it:

    foo                  ; => 3
  3. A list evaluates to the return value of a "call".

    (+ 1 2 3)            ; => 6
    (= 1 2)              ; => false
    (if true "y" "n")    ; => "y"

Calls

If the first element of a list is a function, then the rest of the elements are evaluated and passed to it (prefix notation).

; String concatenate function
(str "Hello " "World")  ; => "Hello World"

; Arithmetic functions
(= 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 the language's few special forms, then the rest of the elements are passed to it unevaluated. (There are only 22 special forms.)

(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 resulting value of the call is evaluated. Let's illustrate that difference with the following diagram:

calls

This difference in evaluation allows macros to act as 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.

Simple substitutions

There are a few macro characters that help make the language succinct by performing simple substitutions (not full macros):

; short-hand for creating a simple function:
; #(...) => (fn [args] (...))

#(* 3 %)         ; => (fn [x] (* 3 x))

#(* 3 (+ %1 %2)) ; => (fn [x y] (* 3 (+ x y)))

That's it for Syntax

You need to know more than syntax to be proficient in a language, of course. But you should now know enough to be comfortable looking around at examples and reasoning about how data is being evaluated and passed around:

; printing to the javascript console
(js/console.log "Hello World!")

; creating local bindings (constants)
(let [a (+ 1 2)
      b (* 2 3)]
  (js/console.log "The value of a is" a)
  (js/console.log "The value of b is" b))

; generate a sequence of numbers
(range 4) ; => (0 1 2 3)

; generate first four multiples of 3
(map #(* % 3) (range 4))           ;=> (0 3 6 9)

; count elements in a sequence
(count "Bob")     ; => 3
(count [4 5 2 3]) ; => 4

; select three letter names from a list
(def names ["Bob" "David" "Sue"])
(filter #(= (count %) 3) names) ; => ("Bob" "Sue")

(Don't worry about getting lost in parentheses. All modern text editors will highlight the corresponding ones and will indent your code automatically for readability, as is standard in every other language.)

ClojureScript vs JSX in HTML templating

See Jumping from HTML to ClojureScript to see how ClojureScript's syntax solves the verbosity/flexibility problems faced in the JS community by JSX.

A complete reference

The syntax section of the ClojureScript API reference is a comprehensive look at the possible syntax forms and even shows the source code for how each are read/parsed.

Useful Resources

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.)

  1. Reading through the ClojureScript Wiki
  2. Reading the book ClojureScript Up and Running
  3. Reading the book Clojure Programming
  4. Doing ClojureScript Koans
  5. Reading Clojure Style Guide
  6. Reading Clojure Programming By Example
  7. Reading Clojure Functional Programming
  8. Thumbing through Clojure Core API
  9. Reading ClojureScript - Differences from Clojure - Host Interop for accessing javascript properties like (.-Infinity js/window) and functions like (.sqrt js/Math 25).
  10. Reading JavaScript to ClojureScript synonyms
  11. Experimenting in lein repl for Clojure REPL.
  12. Experimenting in http://clojurescript.net/ for ClojureScript REPL with a browser context.
  13. Reading docstrings of functions I encounter with (doc <funcname>) in REPL.
  14. Miscellaneous ClojureScript things to know

More Repositories

1

blinky

Exploring peripheral vision in games (using Quake)
C
687
star
2

history-of-lisp-parens

a history of Lisp's most notorious artifact, parentheses
567
star
3

t3tr0s-slides

interactive guide to tetris in cljs
Clojure
274
star
4

IsometricBlocks

A tutorial on how to render isometric blocks in the correct order.
HTML
200
star
5

pacman-mazegen

researching solutions for generating Pac-Man mazes
HTML
187
star
6

solar-system-of-js

Visualize the languages on the JS platform
Clojure
169
star
7

visualizing-projections

interactive visualization of projections
JavaScript
127
star
8

jumping-from-html-to-clojurescript

a strangely intuitive path to ClojureScript from HTML
59
star
9

super-hexagon-unwrapper

a neat math hack for Super Hexagon
Python
51
star
10

flex-fov

intelligent defaults for displaying any FOV
Java
49
star
11

cljs-pprint

porting clojure.pprint to clojurescript (pretty-printing)
Clojure
45
star
12

pacman

JavaScript
44
star
13

bl1nd-ld28

1D game for Ludum Dare 28
CSS
44
star
14

PterodactylAttack

iPhone game in JS
JavaScript
32
star
15

gh4st

A.I. puzzle experiment based on pacman ghosts
Clojure
32
star
16

t3tr0s-bare

clojurescript tetris - stripped down T3TR0S
Clojure
27
star
17

hammock

tie two trees together to track a transformation
Clojure
27
star
18

parinfer

Clojure
24
star
19

parinfer-codemirror

Parinfer layer for CodeMirror
JavaScript
16
star
20

github-markdown-hacks

undocumented github markdown things
14
star
21

ratios

visual method for simplifying numbers
JavaScript
13
star
22

js-in-cljs-case-study

CSS
11
star
23

MayanCalendar

an animated Mayan Calendar
JavaScript
11
star
24

locus

gradual focusing for lisp syntax
9
star
25

highlight-tree-sitter

create syntax-highlighted code using tree-sitter
JavaScript
8
star
26

macos-trackpad-demo

show raw touch points from macOS trackpad
Swift
7
star
27

clojure-the-essential-reference-dash

convert Clojure Essential Ref book to Dash docset
Clojure
6
star
28

ui-testing-braindump

6
star
29

cube

generalizing 2d, 3d, and 4d cubes
JavaScript
5
star
30

HygoonMosaic

Texture Packer
Python
5
star
31

a-tour-through-the-visualization-zoo

HTML
5
star
32

handhold-philosophy

a hypothesis on maintaining momentum when doing something difficult or unfamiliar
3
star
33

Shipmates-LD29

A game for the 29th Ludum Dare game jam.
C
3
star
34

Svg2Canvas

an offline backup of an existing Svg2Canvas processor
JavaScript
3
star
35

ld33-gh4st

Clojure
2
star
36

OneTwentyOne

A collaborative flickering mosaic...
JavaScript
2
star
37

calc

JavaScript
2
star
38

how-we-made-a-game

Writing about 9 months of indie game development.
JavaScript
2
star
39

Fun2D

a game-maker created for a 6th grade program
C#
2
star
40

flexfov-sm64

C
1
star
41

SeeThinkDesignProduce

notes from STDP lectures - May 6, 2014
1
star
42

pteroattack.com

The landing page for the game Pterodactyl Attack
JavaScript
1
star
43

textAnimFrame

JavaScript
1
star
44

Godel

notes from the book, Gรถdel's Proof
1
star
45

yelo-battery

C++
1
star
46

cljs-nodebot

Clojure
1
star