Skip to content

Commit 9747628

Browse files
author
Shaun Williams
committed
simplify and reorder
1 parent 4edda08 commit 9747628

File tree

1 file changed

+104
-144
lines changed

1 file changed

+104
-144
lines changed

README.md

Lines changed: 104 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
# Starting with CLJS
1+
# ClojureScript
22

33
Hello and welcome to ClojureScript (CLJS)! It is a new language for front-end
44
web development (i.e. a language that compiles to Javascript for use in the
55
browser).
66

7+
## The Pitch
8+
79
CLJS is fundamentally different from Javascript and other compile-to-JS
810
languages like Dart, CoffeeScript, and LiveScript. It uses a more powerful yet
911
simpler syntax, it employs useful defaults to combat the "new spaghetti code"
@@ -18,203 +20,161 @@ __Leiningen__ is the command-line tool used for building ClojureScript projects.
1820
- [Install Leiningen](http://leiningen.org/).
1921

2022
If you want to setup __Sublime Text Editor__ to highlight ClojureScript files,
21-
open any file with a `.cljs` extension in Sublime, then select `View` >
22-
`Syntax` > `Open all with current extension as...` > `Clojure`:
23-
24-
![sublime-cljs-syntax](img/sublime-cljs-syntax.png)
25-
26-
## Learning
27-
28-
Here are the resources and steps that I took while learning ClojureScript.
29-
(Most resources covering Clojure also apply to ClojureScript, since they
30-
share a significant subset with each other.)
31-
32-
1. Reading the book [ClojureScript Up and Running](http://synrc.com/publications/cat/Functional%20Languages/Clojure/Oreilly.ClojureScript.Up.and.Running.Oct.2012.pdf)
33-
1. Reading the book [Clojure Programming](http://bit.ly/clojurebook)
34-
1. Doing [ClojureScript Koans](http://clojurescriptkoans.com)
35-
1. Reading [ClojureScript Style Guide](https://github.com/bbatsov/clojure-style-guide)
36-
1. Reading [Clojure Programming By Example](http://en.wikibooks.org/wiki/Clojure_Programming/By_Example)
37-
1. Reading [Clojure Functional Programming](http://clojure.org/functional_programming)
38-
1. Thumbing through [Clojure Core API](http://clojure.github.io/clojure/clojure.core-api.html)
39-
1. Reading [ClojureScript - Differences from Clojure - Host Interop](https://github.com/clojure/clojurescript/wiki/Differences-from-Clojure#wiki-host-interop) for accessing javascript properties like `(.-Infinity js/window)` and functions like `(.sqrt js/Math 25)`.
40-
1. Reading [Javascript to ClojureScript synonyms](http://kanaka.github.io/clojurescript/web/synonym.html)
41-
1. Experimenting in `lein repl` for Clojure REPL.
42-
1. Experimenting in <http://clojurescript.net/> for ClojureScript REPL with a browser context.
43-
1. Reading docstrings of functions I encounter with `(doc <funcname>)` in REPL.
23+
open any file with a `.cljs` extension in Sublime, then select:
4424

45-
_What follows is my attempt to guide you through ClojureScript's fundamentals
46-
and advantages over other languages for the web._
25+
```
26+
View > Syntax > Open all with current extension as... > Clojure
27+
```
4728

48-
### Data Syntax
29+
## Syntax
4930

50-
Though its syntax is unfamiliar and different, ClojureScript has a surprisingly
51-
simple foundation with wide benefits. And one can it learn quickly.
31+
#### Data
5232

53-
This is a __`number`__:
33+
There is __literal data__:
5434

5535
```clj
36+
; number
5637
1.23
57-
```
58-
59-
This is a __`string`__:
6038

61-
```clj
39+
; string
6240
"foo"
63-
```
64-
65-
A __`keyword`__ is like a string, but it is primarily used as a "key" to
66-
retrieve data from a `map`. (more on this later)
6741

68-
```clj
42+
; keyword (like strings, but used as map keys)
6943
:foo
70-
```
71-
72-
A __`symbol`__ is used as the name of some saved value. (more on creating
73-
these later)
7444

75-
```clj
76-
foo
77-
```
45+
; vector (array)
46+
[:bar 3.14 "hello"]
7847

79-
A __`list`__ is surrounded by parentheses, and its elements are separated by
80-
whitespace. It can contain elements of any type, even other lists.
48+
; map (associative array)
49+
{:msg "hello" :pi 3.14 :primes [2 3 5 7 11 13]}
8150

82-
```clj
83-
(foo :bar 3.14 "hello")
51+
; set (distinct elements)
52+
#{:bar 3.14 "hello"}
8453
```
8554

86-
A __`vector`__ is similar to a list. It uses square brackets, but keep in
87-
mind, the actual _significant_ difference is how they are "evaluated" (covered
88-
later).
55+
And there is __symbolic data__:
8956

9057
```clj
91-
[foo :bar 3.14 "hello"]
58+
; symbol (represents a named value)
59+
foo
60+
61+
; list (represents a "call")
62+
(foo :bar 3.14)
9263
```
9364

94-
A __`map`__ is an associative collection that "maps" a key value to another value.
95-
It is denoted by curly brackets. (Keys are often `keywords` but can be anything)
65+
#### Evaluation
9666

97-
```clj
98-
{:msg "hello" :pi 3.14 :primes [2 3 5 7 11 13]}
99-
```
67+
ClojureScript can evaluate data to create a new "value" from it.
10068

101-
Since commas and newlines are considered whitespace in ClojureScript,
102-
you can use them to make `map`s more readable:
69+
1. Literal data evaluates to itself, of course:
10370

104-
```clj
105-
{:msg "hello", :pi 3.14, :primes [2 3 5 7 11 13]}
106-
; or
107-
{ :msg "hello"
108-
:pi 3.14
109-
:primes [2 3 5 7 11 13] }
110-
```
71+
```clj
72+
1.23 ; => 1.23
73+
"foo" ; => "foo"
74+
[:bar 3.14 "hello"] ; => [:bar 3.14 "hello"]
75+
```
11176

112-
### And that's all the syntax
77+
1. A __symbol__ evaluates to the value bound to it:
11378

114-
Now this is where it gets interesting! All ClojureScript code is written in
115-
its own Data Syntax which we just covered. The big revelation here is that
116-
"Code is just Data".
79+
```clj
80+
foo ; => 3
81+
```
11782

118-
In particular, it is the `list` data type that is treated as code. For
119-
example, if `foo` is a function, then this is how you call it with some
120-
parameters.
83+
1. A __list__ evaluates to the return value of a "call".
12184

122-
```clj
123-
(foo :bar 3.14 "hello")
124-
```
85+
```clj
86+
(+ 1 2 3) ; => 6
87+
(= 1 2) ; => false
88+
(if true "y" "n") ; => "y"
89+
```
12590

126-
In fact, all the usual arithmetic operators are functions too.
127-
For example, `+` `-` `*` `=` `<` `>` are all functions.
91+
#### Calls
92+
93+
If the first element of a list is a __function__, then the rest of the elements
94+
are evaluated and passed to it.
12895

12996
```clj
97+
; String concatenation
98+
(str "Hello" "World")
99+
100+
; Arithmetic
130101
(= a b) ; equality (true or false)
131102
(+ a b) ; sum
132103
(- a b) ; difference
133104
(* a b c) ; product
134105
(< a b c) ; true if a < b < c
135-
```
136-
137-
And here is an `if` expression:
138-
139-
```clj
140-
(if (= a b c) ; <-- determines if a=b=c
141-
(foo 1) ; <-- called if true
142-
(bar 2) ; <-- called if false
143-
)
144-
```
145-
146-
Notice that the `if` expression above is actually a list of lists. Let's look
147-
at a simpler example of a list of lists to see how it is __evaluated__ step by
148-
step:
149-
150-
```clj
151-
(+ k (* 2 4))
152-
```
153-
154-
This is adding the value of `k` to the product of 2 and 4. Assuming that `k`
155-
is a symbol representing a var of value 3, the evaluation is carried out as
156-
follows:
157106

158-
```clj
159-
(+ k (* 2 4)) ; as we stated, k evalutes to 3
107+
; Evaluation Steps
108+
(+ k (* 2 4)) ; assume k evalutes to 3
160109
(+ 3 (* 2 4)) ; (* 2 4) evaluates to 8
161110
(+ 3 8) ; (+ 3 8) evalutes to 11
162111
11
163112
```
164113

165-
Notice that both `lists` and `symbols` are __evaluated__ to new values. This
166-
is a crucial step in understanding ClojureScript.
167-
168-
__Numbers, strings, and keywords simply evaluate to themselves__, meaning
169-
ClojureScript takes them at face value without doing anything extra.
114+
If the first element of a list is one of 16 __special forms__, then the rest of
115+
the elements are passed to it _unevaluated_.
170116

171117
```clj
172-
123 ; => 123
173-
"foo" ; => "foo"
174-
:foo ; => :foo
175-
```
176-
177-
But as we saw a moment ago, __symbols evaluate to the values they are bound
178-
to__:
118+
(if (= a b c) ; <-- determines if a=b=c
119+
(foo 1) ; <-- only evaluated if true
120+
(bar 2) ; <-- only evaluated if false
121+
)
179122

180-
```clj
181-
(def k 3) ; bind k to the value of 3
182-
k ; => 3
183-
```
123+
; define k as 3
124+
(def k 3) ; <-- notice that k is not evaluated here
125+
; (def needs the symbol k, not its value)
184126

185-
__A vectors evaluates to a vector of its evaluated elements.__ In other words,
186-
it evalutes to itself, but with all its elements evaluated. Same goes for maps.
127+
; make a greeting function
128+
(fn [username] ; <-- expected parameters vector
129+
(str "Hello " username))
187130

188-
```clj
189-
["hello" (+ 1 2)] ; => ["hello" 3]
190-
```
131+
; oops, give the function a name
132+
(def greet (fn [username]
133+
(str "Hello " username)))
191134

192-
```clj
193-
{:msg "hello" :sum (+ 1 2)} ; => {:msg "hello" :sum 3}
135+
(greet "Bob") ; => "Hello Bob"
194136
```
195137

196-
__Lists are evaluated as code__. The full nature of this evaluation depends on
197-
the first element of the list. (functions vs macros vs special forms)
138+
If the first element of a list is a __macro__, then the rest of the elements
139+
are passed to it unevaluated, but the value returned by a macro evaluated.
140+
Let's illustrate that difference:
198141

142+
![calls](img/calls.png)
199143

200-
### Complaints
144+
This difference in evaluation allows macros to act like code-generating
145+
functions. For example, the `defn` macro expands to `def` and `fn`, as we used
146+
separately in a previous example:
201147

202-
Let's immediately address the instinctual complaints we all have when first
203-
encountering this unfamiliar syntax and its potential for lots of parentheses.
204-
205-
Despite the unfamiliarity, you just learned everything you need to know about
206-
the syntax, so it is very simple to learn and keep in one's head.
207-
208-
As with all other languages, readability is improved with standard indentation
209-
practices. It is also trivial to manage parentheses in any editor. For
210-
example, Sublime Text simply underlines matching parens touching your cursor:
148+
```clj
149+
; create a named function using the defn macro
150+
(defn greet [username]
151+
(str "Hello " username))
211152

212-
![sublime-parens1](img/sublime-parens1.png)
153+
; the definition for the defn macro (over-simplified)
154+
(defmacro defn [name args body]
155+
`(def ~name (fn ~args ~body)))
156+
```
213157

214-
Some even allow you to outline all code inside matching parens (using Sublime Text's
215-
"Bracket Highlighter" plugin with "high visibility" enabled):
158+
App developers rarely need to create their own macros, but it is an
159+
indispensible tool for the library developer to give app developers the full
160+
flexibility of the language.
216161

217-
![sublime-parens1](img/sublime-parens1.png)
162+
## Useful Resources
218163

219-
### Benefits
164+
Here are the resources and steps that I took while learning ClojureScript.
165+
(Most resources covering Clojure also apply to ClojureScript, since they
166+
share a significant subset with each other.)
220167

168+
1. Reading the book [ClojureScript Up and Running](http://synrc.com/publications/cat/Functional%20Languages/Clojure/Oreilly.ClojureScript.Up.and.Running.Oct.2012.pdf)
169+
1. Reading the book [Clojure Programming](http://bit.ly/clojurebook)
170+
1. Doing [ClojureScript Koans](http://clojurescriptkoans.com)
171+
1. Reading [ClojureScript Style Guide](https://github.com/bbatsov/clojure-style-guide)
172+
1. Reading [Clojure Programming By Example](http://en.wikibooks.org/wiki/Clojure_Programming/By_Example)
173+
1. Reading [Clojure Functional Programming](http://clojure.org/functional_programming)
174+
1. Thumbing through [Clojure Core API](http://clojure.github.io/clojure/clojure.core-api.html)
175+
1. Reading [ClojureScript - Differences from Clojure - Host Interop](https://github.com/clojure/clojurescript/wiki/Differences-from-Clojure#wiki-host-interop) for accessing javascript properties like `(.-Infinity js/window)` and functions like `(.sqrt js/Math 25)`.
176+
1. Reading [Javascript to ClojureScript synonyms](http://kanaka.github.io/clojurescript/web/synonym.html)
177+
1. Experimenting in `lein repl` for Clojure REPL.
178+
1. Experimenting in <http://clojurescript.net/> for ClojureScript REPL with a browser context.
179+
1. Reading docstrings of functions I encounter with `(doc <funcname>)` in REPL.
180+
1. [Miscellaneous ClojureScript things to know](https://github.com/shaunlebron/ClojureSheet#clojurescript-stuff)

0 commit comments

Comments
 (0)