Clojure Journey VI – Data

Data is the core of all computer application, an information system basically receives information as input, executes operations and produces some output. Data is the core of computation, we execute operations using data, and as programmers we need to have ways of represent data at computer-level.

With this requirement, engineers and computer language hackers, created a way of represent data at software level classifying them in different types, and this type will represent a range of possible data and the way that it will behave when dealing with hardware.

All programming languages has a set of datatypes to deal with basic data, and imagine a language without them is almost impossible, Clojure of course has set of datatypes.

This post can look kind of boring but it’s necessary to study it before we start learning about functions in the next posts. It’ll do my best to this post don’t look boring and be short.

Hosted Types?

As a hosted language on JVM, most of its datatypes are from Java, and as we know, its heavy-tested for more 20 years, with excellent performance and interoperability, as we will see, Clojure strings are java.lang.Strings and so on.

To check type of something in Clojure, just use the function type, let’s start exploring with numbers, Clojure has it’s integer numbers that we already used in our journey when dealing with arithmetical operations:

=> (type 1)
java.lang.Long

As we see, the type is mapped to a Java type (remember that Clojure is build on top of JVM), other common types behave like this:

=> (type "Hello String")
java.lang.String
=> (type true)
java.lang.Boolean
=> (type 42.42)
java.lang.Double
Clojure primitives are java types

As supposed, you can use string to represent text, boolean to represent true/false and double to represent fractional numbers.

Numbers

Most of languages includes a float type, but as you should know, floats is not good enough, so, doubles are default in Clojure.

=> (type (+ 41.0 1.0))
java.lang.Double

floats are not banned at all, and Clojure has it, but it’s not the default, if you want to use it, you need to make a type conversion:

=> (type (float (+ 41.0 1.0)))
java.lang.Float

Just to keep talking about math, Clojure has a type that is not common on most languages, it’s called ratio that is useful to represent fractions:

=> (type 1/3)
clojure.lang.Ratio

And as we already seen, we represent integer numbers with integer type:

=> (type 1)
java.lang.Long

We can do mathematical operations on number as expected, just remember to use the polish notation, as we see in the last post.

=> (- 52 10)
42

One of the most important things to note here, is that if one number is fractional, the result is fractional, but you can do operations with integers and doubles interacting.

=> (- 52.0 10)
42.0

Text

You can represent strings in Clojure just putting any text inside double quotes:

=> (type "I'm a text")
java.lang.String

With the function str you can convert almost everything in String, just try:

=> (type (str 1))
java.lang.String

Clojure has it character type too, just type \ before a single char:

=> (type \t)
java.lang.Character

Logical Values

Logical values are represent by pure true and false, no complexity here!

user=> (type true)
java.lang.Boolean
user=> (type false)
java.lang.Boolean

And do logical operations with it too:

=> (and false false)
false
=> (and true true)
true
=> (or false true)
true
=> (not true)
false

In Clojure we only have two false values false and nil that we will see next.

Keyword

Keyword is a difficult topic to explain, folks coming from Ruby or lisp already know what I’m talking about. They look like string, but aren’t string, but are dedicated to be used as identifiers, they are just themselves, and you common will see as a map key for example.

They start with : fallowed by a text:

=> (type :keyword)
clojure.lang.Keyword

On the next post we’ll see more about keyword when dealing with maps.

Symbols

Symbols usually refers to something else, like functions, values. During the eval process they are evaluated to the value that its referring. To better understand it, let’s do and example.

We define a variable called hello, with the String “Hello Otavio”:

=> (def hello "Hello Otavio")
#'user/hello

Now if we just print the hello, as expected it will the string binded.

=> (println hello)
"Hello Otavio"

And if we check the type of hello:

=> (type hello)
java.lang.String

It will return the type of what is binded to hello and not the type of it, this occurs because evaluator first eval hello and look for what is binded, before call type. To check the true type of hello we need to delay the evaluation as we saw in the last post:

=> (type 'hello)
clojure.lang.Symbol

And that is our symbol. We already used a lot of symbols in this post, other example is the functions that we used:

=> (type 'println)
clojure.lang.Symbol
=> (type '+)
clojure.lang.Symbol
=> (type '-)
clojure.lang.Symbol

As we will see in future, symbols can have a namespace separated from the name by forward slash.

Fun fact from Clojure doc: There are three special symbols that are read as different types – nil is the null value, and true and false are the boolean values.

Regex

Regex has its own datatype in Clojure too, to represent a regex just use a hash fallowed by a string:

=> (type #"regex")
java.util.regex.Pattern

And with no surprise we will have a java datatype Pattern represented.

I will not dive deep into how to use regexs, but in the standard library we have good functions already built to deal with them, check this post if you want to learn more.

And Finally…The emptiness, the void, the villain!

Pay attention on nil monster or it will destory you!!

We’re talking about nil, the value that represent nothing, the emptiness. For those who already code something, you probably know it, in some languages are called Null, nil or None, it can be called a billion dollar mistake (watch this excellent talk anyway).

The rule is simple, nil is type nil and to represent nil just type nil:

=> (type nil)
nil

Next steps

On the next post we will see the collections, and understand each one and its use cases, for now to don’t extend this post we’ll finish here.

As a nice exercise for this post, check Clojure cheatsheet and you’ll see nice functions to deal with these datatypes.

Conclusions

Clojure has simple datatypes, and a uncommon datatype called ratio, one of the interesting things its that Clojure uses Double by default, so we avoid to use Floats.

Final thought

If you have any questions that I can help you with, please ask! Send an email (otaviopvaladares at gmail.com), pm me on my Twitter or comment on this post!