You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/introduction/clojure-in-15-minutes.md
+51-46Lines changed: 51 additions & 46 deletions
Original file line number
Diff line number
Diff line change
@@ -1,25 +1,18 @@
1
1
# Clojure in 15 minutes
2
2
3
-
A quick tour of the Clojure syntax and common functions, which is so terse you can read through this page in around 15 minutes and have a basic understanding of the language.
3
+
A quick tour of the Clojure syntax and common functions. The syntax is quite minimal so this should take around 15 minutest to read through (it may take longer to get comfortable with).
4
4
5
5
!!! HINT "Try the code out in the REPL"
6
6
[:fontawesome-solid-book-open: Start a Clojure REPL](/clojure/clojure-cli/repl/) or use a [:fontawesome-solid-book-open: Clojure aware editor](/clojure/clojure-editors/) connected to a REPL and experiment with these code examples.
7
7
8
8
Using the REPL provides instant feedback on each expression as they are evaluated, greatly increasing your understanding.
9
9
10
10
11
-
## Comments
12
-
13
-
`;;` two semi-colons for a line comment, `;` single semi-colon to comment the rest of the line
14
-
15
-
`#_` comment reader macro to comment out the next form
16
-
17
-
`(comment ,,,)` form to comment all the containing forms, useful to [:fontawesome-solid-book-open: separate experimental and established code](/clojure/introduction/repl-workflow/#rich-comment-blocks-living-documentation) in a namespace.
18
-
19
-
20
11
## Clojure expressions
21
12
22
-
Clojure is mostly written with "expressions", a lists of elements inside parentheses, `()`, separated by space characters.
13
+
Clojure is written with "expressions", a lists of elements inside parentheses, `()`, separated by space characters.
14
+
15
+
An expression is made of one or more forms, a form is a general term for anything that legally evaluates in Clojure, e.g. a number, string function definition, etc.
23
16
24
17
Clojure evaluates the first element in an expression as a function call. Additional elements in the expression are passed as value arguments to the called function.
25
18
@@ -33,6 +26,16 @@ Clojure evaluates the first element in an expression as a function call. Additi
33
26
(map inc (range 0 99))
34
27
```
35
28
29
+
30
+
## Comment
31
+
32
+
`;;` two semi-colons for a line comment, `;` single semi-colon to comment the rest of the line
33
+
34
+
`#_` comment reader macro to skip specific parts of code, e.g. `(+ 1 2 #_(* 3 4))` is read as `(+ 1 2)`
35
+
36
+
`(comment ,,,)` form to comment all the containing forms, useful to [:fontawesome-solid-book-open: separate experimental and established code](/clojure/introduction/repl-workflow/#rich-comment-blocks-living-documentation) in a namespace. Note that `(comment )` returns `nil` when evaluated so shouldn't be used inside other code.
37
+
38
+
36
39
## Organising Clojure
37
40
38
41
Clojure code is organised into one or more namespaces. The namespace represents the directory path and file name that contains the code of the particular namespace.
@@ -152,16 +155,16 @@ A predicate is a function that returns a boolean `true` or `false` value and by
152
155
153
156
The most common data collections in Clojure:
154
157
155
-
*`(1 2 "three")` or `(list 1 2 "three")` - a list of values read from start to end (sequential access)
156
-
*`[1 2 "three"]` or `(list 1 2 "three")` - a vector of values with index (random access)
157
-
*`{:key "value"}` or `(hash-map :key "value")` - a hash-map with zero or more key value pairs (associative relation)
158
-
*`#{1 2 "three"}` or `(set 1 2 "three")` - a unique set of values
158
+
*List literal `(1 2 "three")` or function call`(list 1 2 "three")` - a list of values read from start to end (sequential access)
159
+
*Vector literal `[1 2 "three"]` or function call `(vector 1 2 "three")` - a vector of values with index (random access)
160
+
*Hash-map literal `{:key "value"}` or function call`(hash-map :key "value")` - a hash-map with zero or more key value pairs (associative relation)
161
+
*Set literal `#{1 2 "three"}` or function call`(set 1 2 "three")` - a unique set of values
159
162
160
-
A list `()` is evaluated as a function call. The first element of the list the name of the function to call and additional values are arguments to the function.
163
+
A literal list `()`expression is evaluated as a function call. The first element in the list is the name of the function to call and additional values are arguments to the function (assuming the function takes arguments).
161
164
162
-
The `'` quote function informs the Clojure reader to treat the list as data only.
165
+
The `'`is syntax short-cut for the `quote` function which informs the Clojure reader to treat a list as data only. A quoted list is not evaluated as a function.
163
166
164
-
!!! EXAMPLE "A quoted list is treated as data"
167
+
!!! EXAMPLE "Evaluating a quoted list returns that list as data"
165
168
```clojure
166
169
'(1 2 3) ; => (1 2 3)
167
170
```
@@ -180,11 +183,12 @@ Only lists are sequences
180
183
181
184
Sequences are an interface for logical lists, which can be lazy. "Lazy" means that a sequence of values are not evaluated until accessed.
182
185
183
-
A lazy sequence enables the use of large or even an infinite series, like so:
186
+
The `range` function generates an 'infinite' series of numbers, e.g. `(range) ; => (0 1 2 3 4 ...)`
187
+
188
+
Lazily evaluating a sequence enables the use of large or even an infinite series without consuming all the computer memory, like so:
184
189
185
190
!!! EXAMPLE "Lazy sequences"
186
191
```clojure
187
-
(range) ; => (0 1 2 3 4 ...) - an infinite series
188
192
(take 4 (range)) ; (0 1 2 3) - lazyily evaluate range and stop when enough values are taken
189
193
```
190
194
@@ -202,20 +206,20 @@ Use conj to add an item relative to the type of collection, to the beginning of
202
206
(conj '(123) 4) ; => (4 1 2 3)
203
207
```
204
208
205
-
Use concatto add lists or vectors together
209
+
Use `concat` (concatenate) to add sequences (lists or vectors) together
206
210
207
211
```clojure
208
212
(concat [12] '(34)) ; => (1 2 3 4)
209
213
```
210
214
211
-
Use filter, map to interact with collections
215
+
`filter` maps another function over a collection of values, returning the values that returned true from the function used by filter
212
216
213
217
```clojure
214
218
(map inc [123]) ; => (2 3 4)
215
219
(filter even? [123]) ; => (2)
216
220
```
217
221
218
-
Use reduceto reduce them
222
+
`reduce` uses a function over a collection of values to return a combined result
219
223
220
224
```clojure
221
225
(reduce + [1234])
@@ -230,18 +234,18 @@ Reduce can take an initial-value argument too
230
234
; => [3 2 1]
231
235
```
232
236
233
-
Equivalent of `(conj (conj (conj [] 3) 2) 1)`
237
+
The above is the equivalent of `(conj (conj (conj [] 3) 2) 1)`
234
238
235
239
236
-
## Annonymous Functions
240
+
## Anonymous Functions
237
241
238
-
Use `fn` to create new functions that defines some behaviour. `fn` is referred to as an anonymous fuction as it has no external name to be referenced by and must be called within a list form.
242
+
Use `fn` to create new functions that defines some behaviour. `fn` is referred to as an anonymous function as it has no external name to be referenced by and must be called within a list form.
239
243
240
244
```clojure
241
245
(fn hello [] "Hello World")
242
246
```
243
247
244
-
Wrap a `(fn ,,,)`form in parens to call it and return the result.
248
+
Wrap an anonymous function `(fn ,,,)`expression in another list to call it and return the result.
245
249
246
250
!!! EXAMPLE "Call an anonymous function"
247
251
```clojure
@@ -267,7 +271,7 @@ The `var` name bound to the function can now be called anywhere in the namespace
267
271
(fn hello [] "Hello World"))
268
272
```
269
273
270
-
!!! EXAMPLE "Evaluate annonymous function by evaluating its name"
274
+
!!! EXAMPLE "Evaluate anonymous function by evaluating its name"
271
275
```clojure
272
276
hello-world
273
277
```
@@ -287,7 +291,7 @@ It is more common to use the `defn` macro to define a function. This is the sam
287
291
"Hello World")
288
292
```
289
293
290
-
`#'user/hello-world` is the value returned from evaluating the expression, showing the fully qualified name of the function. Note: the fully qualified name will be different when defined in a differnt namespace than `user`.
294
+
`#'user/hello-world` is the value returned from evaluating the expression, showing the fully qualified name of the function. Note: the fully qualified name will be different when defined in a different namespace than `user`.
291
295
292
296
293
297
> A `defn` function has the scope of the current namespace, so can be called anywhere in the namespace or in a namepace that has used `require` to include this namespace.
@@ -328,7 +332,7 @@ The correct number of arguments must be used when calling a function, or an erro
328
332
```
329
333
330
334
331
-
Clojure supports multi-variadic functions, allowing one function definition to respond to a function call with different number of arguments. This provides a simple form of polymorphism based on the number of arguments.
335
+
Clojure supports multi-variadic functions, allowing one function definition to respond to a function call with different number of arguments. This provides a simple form of polymorphism based on the number of arguments.
332
336
333
337
```clojure
334
338
(defnhello-polly
@@ -416,13 +420,13 @@ Use assoc to add new keys to hash-maps
416
420
(assoc keymap :d4) ; => {:a 1, :b 2, :c 3, :d 4}
417
421
```
418
422
419
-
But remember, clojure types are immutable!
423
+
But remember, Clojure types are immutable!
420
424
421
425
```clojure
422
426
keymap ; => {:a 1, :b 2, :c 3}
423
427
```
424
428
425
-
Use dissocto remove keys
429
+
Use `dissoc` function to remove keys from a hash-map
426
430
427
431
```clojure
428
432
(dissoc keymap :a:b) ; => {:c 3}
@@ -435,13 +439,13 @@ Use dissoc to remove keys
435
439
(set [123123321321]) ; => #{1 2 3}
436
440
```
437
441
438
-
Add a member with conj
442
+
Add a value to a set with `conj` (conjoin)
439
443
440
444
```clojure
441
445
(conj #{123} 4) ; => #{1 2 3 4}
442
446
```
443
447
444
-
Remove one with disj
448
+
Remove one value from a set with `disj` (disjoin)
445
449
446
450
```clojure
447
451
(disj #{123} 1) ; => #{2 3}
@@ -454,7 +458,7 @@ Test for existence by using the set as a function:
454
458
(#{123} 4) ; => nil
455
459
```
456
460
457
-
There are more functions in the clojure.sets namespace.
461
+
There are more functions in the [clojure.sets namespace](https://clojure.github.io/clojure/clojure.set-api.html).
458
462
459
463
## Useful forms
460
464
@@ -480,7 +484,7 @@ Group statements together with do
480
484
"World") ; => "World" (prints "Hello")
481
485
```
482
486
483
-
Functions have an implicit do
487
+
Functions have an implicit `do` function that will call every expression within a function definition.
484
488
485
489
```clojure
486
490
(defnprint-and-say-hello [name]
@@ -489,7 +493,7 @@ Functions have an implicit do
489
493
(print-and-say-hello"Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff")
490
494
```
491
495
492
-
So does let
496
+
The `let` function also has an implicit `do` function.
493
497
494
498
```clojure
495
499
(let [name "Urkel"]
@@ -499,13 +503,13 @@ So does let
499
503
500
504
## Namespaces and Libraries
501
505
502
-
Namespaces are used to organise code into logical groups. The top of each Clojure file has an `ns` form that defines the namespace name. The domain part of the namespace name is typically the organisation or community name (e.g. GitHub user/organisation)
506
+
Namespaces are used to organise code into logical groups. The top of each Clojure file has an `ns` form that defines the namespace name. The domain part of the namespace name is typically the organisation or community name (e.g. GitHub organisation or user account name)
503
507
504
508
```clojure
505
509
(nsdomain.namespace-name)
506
510
```
507
511
508
-
All Practicalli projects have namespace domains of `practicalli`
512
+
Practicalli projects use a namespace domain of `practicalli` followed by the project name
509
513
510
514
```clojure
511
515
(nspracticalli.service-name)
@@ -524,7 +528,7 @@ A required directive is typically added to a namespace form
524
528
(require [clojure.set :as set]))
525
529
```
526
530
527
-
The functions from clojure.set can be used via the alias name, rather than the fully qualified name, i.e.`clojure.set/intersection`
531
+
Functions from `clojure.set` can be used via the alias name, `set/intersection`, rather than the fully qualified name, `clojure.set/intersection`
528
532
529
533
```clojure
530
534
(set/intersection #{123} #{234}) ; => #{2 3}
@@ -540,7 +544,7 @@ The functions from clojure.set can be used via the alias name, rather than the f
540
544
[clojure.set :as set]))
541
545
```
542
546
543
-
`require` can be used by itself, usually within a rich code block
547
+
`require` can be used as a top level expression (not in an `ns` expression). Requires are often used within a rich code block for experimenting with code.
544
548
545
549
```clojure
546
550
(comment
@@ -552,7 +556,7 @@ The functions from clojure.set can be used via the alias name, rather than the f
552
556
553
557
Clojure is strongly typed, so everything is a type in Clojure.
554
558
555
-
Clojure is dynamically typed, so Clojure infers the type. A type does not need to be specified in the code, making the code simpler and more concise.
559
+
Clojure is dynamically typed, so Clojure infers the type. An explicit type name does not need to be specified in the code, making the code simpler and more concise.
556
560
557
561
Clojure is a hosted language and uses the type system of the platform it runs upon. For example, Clojure uses Java object types for booleans, strings and numbers under the covers.
558
562
@@ -566,7 +570,7 @@ Use `class` or `type` function to inspect the type of some code in Clojure.
566
570
(typenil); The "null" value is called nil
567
571
```
568
572
569
-
Vectors and Lists are java classes too!
573
+
Collections in Clojure have their own type too.
570
574
571
575
```
572
576
(type [1 2 3]); => clojure.lang.PersistentVector
@@ -577,17 +581,18 @@ Vectors and Lists are java classes too!
577
581
Type hints can be used to avoid reflection look-ups where performace critical issues have been identified. Type hints are not required in general.
578
582
[Clojure Type Hints](https://clojure.org/reference/java_interop#typehints){target=_blank .md-button}
579
583
584
+
580
585
## Java Interop
581
586
582
-
Java has a huge and useful standard library, so you'll want to learn how to get at it.
587
+
Java has a large and very useful standard library which is easily accessible from Clojure. The `java.lang` library is available by default.
0 commit comments