Clojure: Basic Syntax

By Xah Lee. Date: . Last updated: .

This page is WORK IN PROGRESS.

comma and space

comma can be used as separator.

;; comma can be used as separator
;; the following are equivalent
(+ 1 2 3) ; 6
(+ 1, 2  , 3) ; 6

comment

Comment start with SEMICOLON to end of line.

; comment start with semicolon
;; by lisp convention
;; comment on a line by itself start with 2 semicolons

(+ 3 4) ; comment after a expression start with one semicolon

Comment can also be written as (comment ), but the comment body must be a valid lisp syntax, cannot be any character. This returns nil.

;; comment can also be written as (comment …)
(comment this is a
block comment.
  (comment block comment can be nested.)
)
;; comment body must be valid clojure syntax.
;; a semicolon by itself is not
(comment : )
;; compiler error

You usually use this form (comment ) to comment out a block of Clojure code.

;; (comment …) is usually used to comment out block of code
(comment
  (+ 3 4)
)

clojure.core/comment

printing

use pr to print. It returns nil.

(pr "aa" "bb" "cc") ; prints "aa" "bb" "cc"
prn
same as pr but with a newline at the end.

pr and prn prints in a machine-readable way. (that is, can be read back by Clojure.)

To print in a human friendly way, use print and println

strings

"some string abc"

to join string (concatenate), use str. clojure.core/str

;; join string
(str "aa" "bb") ;  "aabb"

(str 3 " cats") ;  "3 cats"

substring

Index start at 0. Start index is inclusive. End index is exclusive.

;; get substring, starting at index 1.
(subs "abcd" 1) ;  "bcd"

;; get substring, with start/end indexes.
(subs "abcd" 1 3) ;  "bc"

clojure.core/subs

Clojure string functions

For string functions, use the Clojure library clojure.string. clojure.string - Clojure v1.8 API documentation

Example of calling a function in clojure.string namespace:

; calling function upper-case from namespace clojure.string
(clojure.string/upper-case "bb") ;  BB

Note: slash is used to separate name space.

Call Java's String Methods

Clojure itself doesn't have many string functions. It is common to call Java's methods in Clojure.

To call Java's string method, use the syntax (. java_object method_name args).

For example, there's Java String method named charAt. To use it, do:

;; call Java method on object
(. "abc" charAt 1) ;  \b

A more commonly used syntax to call Java method is (.method_name java_object args)

(.charAt "abc" 1) ;  \b

[see Clojure: Call Java Method]

Numbers

Numbers can be written in the form baserdigits. For example, the binary number 10 can be written as 2r10, and the hexadecimal 1a can be written as 16r1a

;; binary number input
2r1111 ;  15

;; hexadecimal number input
16r1af ;  431
0x1af ;  431  (this form is from Java)

;; oct number input
8r77 ;  63

;; base 36. using 0 to and a to z as digits
36rj7 ;  691

Arithmetic

;; addition, plus
(+ 3 4)

;; substraction, minus
(- 7 4)

;; can have 3 or more args
(- 7 4 1)

;; multiply, times
(* 2 4)

Here's division, quotient, remainder/mod, and ratio.

;; division
(/ 7 4) ; 7/4  return a ratio. A Clojure datatype

(/ 7 4.) ; 1.75

;; integer quotient
(quot 11 4) ; 2

;; remainder (aka mod)
(rem 11 4) ; 3

Closure does not have a math lib bundled.

To use math function such as sine, use Java's Math class. Like this: (Math/methodName arg)

;; exponentiation. 2 to the power of 3
(Math/pow 2 3) ;  8.0

[see Clojure: Call Java Method]

Converting String and Numbers

;; convert string to number
(bigint "123")
;; convert number to string
(str 123)

clojure.core/str

Codepoint to Character

;; unicode codepoint (integer) to char
(char 97) ; a

clojure.core/char

Comparison Functions

(< 3 7) ; true

(<= 3 7) ; true

(> 3 7) ; false

(>= 3 7) ; false

logic operations:

;; boolean and
(and true false) ; false

;; boolean or
(or true false) ; true

;; boolean not
(not true) ; false

Block of Expressions

Sometimes you need to group several expressions together as one single expression. This can be done with do. (“do” is like lisp's “progn”)

clojure.core/do

(do
    (pr "a")
    (pr "b"))

;; is equivalent to

    (pr "a")
    (pr "b")

Most of the time it's used inside “if”. clojure.core/if

For example:

(if something
    (do ; true
        …
        )
  (do ; else
      …
      )
  )

do returns the last expression in its body.

(do 3 4 ) ;  4

define global variable

Use def to set a value to a variable. Variable does not need to be declared.

;; define a var
(def x 3)
x ; 3

def can be used to change a variable's value.

;; define a var
(def x 3)
(pr x) ;  3

;; reset to 4
(def x 4)
(pr x) ;  4

clojure.core/def

Local Constants: let

To create local constants, use let. It has this form

(let [var1 val1 var2 val2 …] body)

clojure.core/let
(let [x 3] x) ; 3
(def x 4)

(let [x 3]
  (pr x)
) ; 3

(pr x) ; 4

You can bind multiple variables:

(let [x 3
      y 4]
  (+ x y)) ; 7

Later variable can use values of previous variables:

(let [x 3
      y x]
  (+ x y)) ; 6

the value part can be any expression.

(let [x 3
      y (+ 2 x)]
  (+ x y)) ; 8

Binding Form

The first arg of let is called “binding form”. It is also used in function definition. [see Clojure: Functions]

Clojure's binding form is very flexible. You can do Destructure Binding. [see Clojure: Binding Forms, Destructuring]

True and False

The following are builtin literals.

Clojure nil is Java's null.

false and nil are false, everything else evaluates to true in true/false context.

(if nil 1 2) ; 2

If Then Else

The form for if statement is: (if test body).

If you want a “else” part, the form is (if test true_body false_body). Use a (do ) to group the bodies.

if returns the value of the evaluated branch.

Example:

(if (< 3 2) 9 ) ;  nil
(if (< 3 2) "yes" "no" ) ;  "no"
(if nil 3 4 )  ;  4

Iteration

Here's basic functions related to iteration:

(for [i (range 7)] (inc i)) ; (1 2 3 4 5 6 7)

clojure.core/range clojure.core/inc

Recursion

A function that calls itself is called recursion.

In a function definition, If a function calls itself as exit, then such recursion is called tail recursion or linear recursion.

Linear recursion is not nested in nature. You can think of it as “pass and forget”.

What is the difference between tail-recursion and non-tail-recursion?

Tail recursion can be trivially expressed as iteration or linear loop.

In programing languages, some programing language automatically compile tail-recursion into a iteration. (so that, it saves memory, avoiding stackoverflow, etc.) Scheme (programming language) is the language most famous for enforcing the tail-recursion optimization into its compiler, by spec.

Clojure supports recursion. That is, function can call itself.

Clojure also supports manual tail-recursion using recur. That is, the compiler optimize recursion that's linear into a iteration-like construct.

If the recursion is linear recursion, than you can call recur at the place you want to call function itself. The advantage is that there'll be no limit on recursion depth.

clojure.core/recur

clojure.core/loop

Collection and Sequence: list, vector, hash table …

Clojure: Collections (List, Vector, Set, Map, etc), Sequence

Defining a Function

Clojure: Functions

Clojure data types

Clojure is not typed. Variable doesn't have a type, value has type.

Clojure Basic Data Types
nameexampleJava type used
number18java.lang.Number
string"some"java.lang.String
booleantrue, falsejava.lang.Boolean
char\b, \cjava.lang.Character
keyword:xyz, :bbclojure.lang.keyword
nilnilnull
Clojure Basic Compound Data Types
nameexampleJava type used
list'(3 "e" 7)
vector[8 2 "h"]
map{:mary 13 :john 20}java.util.Map
set#{9 2 4}java.util.Set

Clojure Char Data Type Literal

keywords

“keyword” is a primitive datatype in Clojure. Keywords are symbolic identifiers. Usually used as keys for hash table. It's like Ruby's “symbol”.

keywords starts with a :, like this: :abc

To convert a string to keyword, use keyword function.

clojure.core/keyword

keyword is also a function. The work on hasmap and return the corresponding value.

symbols

Clojure symbols is the same as other lisp “symbols”. Symbols are identifiers, but unlike identifier in other languages, Clojure's “symbol” can remain in a unevaluated form.

symbols, eval to themself. Like other lang's variables, but can hold eval.

but symbol is also a function, that can work on hashmap and look themself up.

symbols can include these characters: * + ! - _ ?

global settings often starts and end with a asterisk, for example: *max*

namespace

Clojure: Namespace

regex

Clojure: regex

states, transactions

http://clojure.org/state

refs
{synchronous, coordinated}. ref
agents
{asynchronous, independent}. agent
atoms
{synchronous, independent}. atom
var
like global var. def

“refs” is typical set variable.

(deref val) is same as @val

transactions

“transactions” is like database transactions. Process inside a transaction happen together or not at all, there is no possibility of partial success. (this property is often called “atomicity”)

“transactions” are isolated. No 2 transactions see each other.

dosync creates a transaction. Other wise it's similar to do. clojure.core/dosync

ref-set is for setting a ref. It can only be used within a transaction. clojure.core/ref-set

alter is like ref-set, except it takes a function and other args. clojure.core/alter

atom

atom is like ref, except it's rather for independent entities (update that do not need to be coordinated with others).

agents (asynchronous)

most useful.

clojure.core/agent

thread-local state: var, def

clojure.core/bind

validator and watch

clojure.core/set-validator!

clojure.core/add-watch

understanding clojure

reader forms

symbols begin with a non-numeric character. Can contain 0 to 9, a to z, * + ! - _ ?

/ is used once to separate namespaces.

. has special meaning — it can be used one or more times in the middle of a symbol to designate a fully-qualified class name, for example, 「java.util.BitSet」, or in namespace names.

Symbols beginning or ending with . are reserved by Clojure.

Symbols containing / or . are said to be 'qualified'.

Symbols beginning or ending with : are reserved by Clojure. A symbol can contain one or more non-repeating ':'s.

forms
lisps refer to its syntax units as “forms”. For example, (+ 3 4) is a form. Anything that returnsa value is a form.
literal
a form that eval to itself. String "…", number, character \b, are literals. true, false, nil, are also literals.
symbol
Symbols are like other lang's identifiers, except that lisp symbol is a identity that can be held unevaluated and be manipulated in unevaluated state. For example, if x has value of 3 (def x 3), then 'x eval to the symbol “x” itself, not its value. Macros are possible because of this. (You can think of “symbol” as a string, a label, a identifier.)
expressions
a form made of other forms. Typically they are enclosed by brackets. For example, list (…), vector […], map {…}. Normally, a form is a function in the form of a list 「(‹head› …)」. The first element is the symbol of the function. The rest are arguments, and are evaluated in order.
special form
a form that has different evaluation order or special in some other way. For example, if is a special form. http://clojure.org/special_forms

Clojure


misc