-
Book Overview & Buying
-
Table Of Contents
-
Feedback & Rating
Clojure Programming Cookbook
By :
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:
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\backspaceUnicode 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:
project.clj:[org.clojure/math.numeric-tower "0.0.4"]
expt and sqrt in the library: (require '[clojure.math.numeric-tower :as math])
(math/expt 2 10)
;;=> 1024
(math/sqrt 10)
;;=> 3.1622776601683795
Change the font size
Change margin width
Change background colour