In this recipe, we will review primitive data types that Clojure supports and a few functions that manipulate these types. Here, we will review the following:
Using numbers
Using strings and characters
Using booleans and nil
Using keywords and symbols
You only need REPL, as described in the previous recipe, and no additional libraries. Start REPL so that you can review the sample code of primitive types immediately in this recipe.
Let's start with numbers in Clojure data types.
The +
function returns the sum of numbers. You can specify any number of numbers as arguments:
(+ 1 2) ;;=> 3 (+ 1 2 3) ;;=> 6 (+ 1.2 3.5) ;;=> 4.7
The -
function subtracts the numbers. If a single argument is supplied, it returns the negation of the numbers:
(- 3 2) ;;=> 1 (- 1 2 3) ;;=> -4 (- 1) ;;=> -1
The *
function returns the product of numbers:
(* 5 2) ;;=> 10 (* 1 2 3 4 5) ;;=> 120
The /
function returns the numerator divided by all of the denominators. It is surprising for beginners of Clojure that if the numerator is not indivisible by the denominators, it returns a simple fraction. You can check the name of the class by the class function.
In the following example, 10
divided by 3
returns 10/3
and not 3.3333333...
(/ 10 5) ;;=> 2 (/ 10 3) ;;=> 10/3
To obtain numerical figures after a decimal point, cast the result by a float
or double
function:
(float (/ 10 3)) ;;=> 3.3333333 (double (/ 10 3)) ;;=> 3.333333333333333
The quot
function returns the quotient of dividing the numerator by the denominator, and the decimal point is suppressed. rem
returns the remainder of dividing the numerator by the denominator:
(quot 10 3) ;;=> 3 (rem 10 3) ;;=> 1
Clojure supports big numbers, and they are Java's BigDecimal
. The bigdec
function casts any number to BigDecimal
. The suffix M
denotes BigDecimal
. Though it can express very large numbers, it cannot express repeating decimals and causes an error:
(bigdec (/ 10 2)) ;;=> 5M (bigdec (/ 10 3)) ;; ArithmeticException Non-terminating decimal expansion; no exact representable decimal result. ;; java.math.BigDecimal.divide (BigDecimal.java:1690)
Clojure also provides large integers, clojure.lang.BigInt
. It is equivalent to Java's java.math.BigInteger
:
(= (bigint 10) 10N) ;;=> true
Clojure strings are Java's String(java.lang.String
) enclosed by double quotes (""
):
"Hello world ! " ;;=> "Hello world ! "
Clojure has good interoperability with Java, and it's easy to call Java's member methods from Clojure. In the following example, the code calls the concat
method in Java's String class:
(.concat "Hello " "world !") ;;=> "Hello world !"
The following syntax is how to call Java's member methods from Clojure:
(.method-name object arg1 arg2 ...)
The first argument is a dot (.
) prefix followed by the method name, then the object and its arguments.
The equivalent Java code is as follows:
String str = "Hello ".concat("world !");
The str
function is similar to the concat
method, but it can take an arbitrary number of arguments:
(str "Hello " "world !" " Clojure") ;;=> "Hello world ! Clojure"
To examine the length of the string, use the length
method or count
function:
(.length "Hello world !") ;;=> 13
clojure.string
is a built-in Clojure library to manipulate strings. Here, we show some functions in clojure.string
:
(clojure.string/blank? " ") ;;=> true (clojure.string/trim " Hello ") ;;=> "Hello" (clojure.string/upper-case "clojure") ;;=> "CLOJURE" (clojure.string/capitalize "clojure") ;;=> "Clojure" (clojure.string/lower-case "REPL") ;;=> "repl"
Let's go to Clojure character type. Characters in Clojure are java.lang.Character
and are preceded by a backslash (\
):
\a ;;=> \a
The int
function gets the integer value of a character. Meanwhile, char
gets an integer value from a character:
(int \a) ;;=> 97 (char 97) ;;=> \a
The seq
function returns a sequence of characters from a string, and str
makes a string from characters:
(seq "Hello world!") ;;=> (\H \e \l \l \o \space \w \o \r \l \d \!) (str \C \l \o \j \u \r \e) ;;=> "Clojure"
Clojure's booleans are java.lang.Boolean
, and their values are true
and false
:
true ;;=> true false ;;=> false (= 1 1) ;;=> true (= 1 2) ;;=> false (= "Hello" "Hello") ;;=> true (= "Hello" "hello") ;;=> false
The not
function returns true
if an expression is logically false. It returns false
otherwise:
(not true) ;;=> false (not false) ;;=> true (not= 1 2) ;;=> true (not true) ;;=> false
The true?
function returns true
if the expression is true; otherwise, it returns false
. The false?
function returns false
if the expression is true; otherwise, it returns true
:
(true? (= 1 1)) ;;=> true (false? (= 1 1)) ;;=> false
The nil
function means nothing, or the absence of a value. The nil
function in Clojure is almost equivalent to the null
function in Java. nil
is logically false in Clojure conditionals. nil
is often used as a return value to indicate false:
(if nil true false) ;;=> false
nil
is the return value used to indicate an empty sequence:
(seq []) ;;=> nil
nil
is returned by default when a map collection looks up and can't find a given key:
(get {:a 1 :b 2} :c) ;;=> nil
The function def
binds global symbols to their values. The next example shows the def
binding the pi
symbol to a value (3.14159265359
):
(def pi 3.14159265359) ;;=> #'user/pi pi ;;=> 3.14159265359 pi-not-bind ;;=> CompilerException java.lang.RuntimeException: Unable to resolve symbol: ;; pi-not-bind in this context, compiling:(/tmp/form-init1426260352520034213.clj:1:7266)
Keywords are similar to symbols, but keywords evaluate to themselves:
:key1 ;;=> :key1
Keywords are used to identify things, so they are often used in Clojure's map:
(def person {:name "John McCarthy" :country "USA"}) ;;=>#'living-clojure.core/person
Clojure primitive data types are mostly Java classes, but some data types are Clojure's own classes.
For numbers, Clojure's integers are java.lang.Long
and floating point numbers are java.lang.Double
. bigInt
and ratios are clojure.lang.BigInt
and clojure.lang.Ratio
respectively:
(class 1) ;;=> java.lang.Long (class 1.0) ;;=> java.lang.Double (class (float 1.0)) ;;=> java.lang.Float (class 5.5M) ;;=> java.math.BigDecimal (class 1N) ;;=> clojure.lang.BigInt (class (/ 10 3)) ;;=> clojure.lang.Ratio
Clojure's strings and characters are java.lang.String
and java.lang.Character
respectively:
(class "Hello world ! ") ;;=> java.lang.String (class \a) ;;=> java.lang.Character (class true)
Clojure's booleans are java.lang.Boolean
:
(class true) ;;=> java.lang.Boolean (class false) ;;=> java.lang.Boolean
Clojure's keywords and symbols are Clojure's own classes:
(class :key) ;;=> clojure.lang.Keyword (class (quote a)) ;;=> clojure.lang.Symbol (class nil) ;;=> nil
Clojure supports hexadecimal and octal notations:
0xff ;;=> 255 0400 ;;=> 256
Clojure also supports flexible numeral bases. You can specify in any base with a radix from 2 to 36:
2r11111 ;;=> 31 16rff ;;=> 255 8r11000 ;;=> 4608 7r111 ;;=>57
There are some specially named character literals, as follows:
\space
\tab
\newline
\return
\formfeed
\backspace
Unicode characters are represented by \uNNNN
in Clojure, like in Java:
\u0031\u0032\u0061\u0062 ;;=> \1 ;;=> \2 ;;=> \a ;;=> \b
Functions in Clojure are also symbols and bind to their functional definitions. The next example shows the value of +
:
+ ;;=> #object[clojure.core$_PLUS_ 0x3c2ace8a "clojure.core$_PLUS_@3c2ace8a"]
To evaluate symbol and return itself, use quote
:
(quote pi-not-bind) ;;=> pi-not-bind
To use the math
library in Clojure, try clojure.math.mumeric-tower
. Here are the steps:
Add the following dependency to
project.clj
:[org.clojure/math.numeric-tower "0.0.4"]
You can use
expt
andsqrt
in the library:(require '[clojure.math.numeric-tower :as math]) (math/expt 2 10) ;;=> 1024 (math/sqrt 10) ;;=> 3.1622776601683795