The Code That Controls Your Money – COBOL runs a lot of software in the world (and probably still running your money), the language is not dying and we don’t have new programmers learning how to program it. This (long) post talks about the history of COBOL, how it changed the world, how and who still use it, and why the leak of COBOL progressions may be a problem.
New courses on distributed systems and elliptic curve cryptography – Martin Kleppmann author of the famous book “Designing Data-Intensive Applications”, published an 8-lecture course on distributed systems, and a tutorial on elliptic curve cryptography. I already started to watch and it’s awesome.
How Facebook is bringing QUIC to billions – HTTP/3 and QUIC are coming, and Facebook already deployed it to all Facebook and Instagram traffic, this post describes how did they do that and effects.
Fast Inverse Square Root – An excellent (but still hard) post explaining the fast inverse square root algorithm and hot it works, famous for its use on Quake III Arena, it was much faster than sqrt().
You may not need Redis with Elixir – This post written by José Valim, the Elixir creator, explains why in some occasions you may not need a Redis while working with Elixir, BEAM already solves most of the problems.
Rust vs Go – Rust and Go are both awesome and this post talks about each, each advantage of each language, and when you may want to use each one.
What’s so great about Go? – A simple post talking about go advantages, if you don’t know about golang or want to learn about it, check it.
Announcing .NET 5.0 – .NET 5.0 is released with a lot of new things, C# 9, F# 5, and much more.
Designing Raspberry Pi 400 – Raspberry Pi 400 is a new product from raspberry that already has a built-in keyboard and comes with a mouse, it’s perfect! This post describes the process of developing it and prototyping.
Moving my serverless project to Ruby on Rails – In the last few years, you probably have read a lot of blog posts about ” moving my application to serverless” but this post is different, it’s talking about moving an application from serverless to old but gold Rails.
How fast are Ractors – Some speed tests around Ractors, the new actor-based concurrent model of Ruby that will be shipped with Ruby 3 this month.
After talking about basic datatypes on our last post of this series, we can talk about array, list, map and sets. Clojure has a rich set of built-in data structures, and the key is know the difference between each one and when use it in to take advantage.
Vector
Let’s start talking about vector or “Array” from those coming from languages that use this term, probably the most popular and easy to learn structure that we’ll talk about here. Th
Vectors in Clojure behaves just like you expect from other languages (sometimes named Arrays), it’s a sequential allocation of memory allocation, where index starts from 0.
Note that just like other languages, vectors are represented with brackets []. You can create a new vector, just using its literal, like this:
=> [1 2 3 4 5]
[1 2 3 4 5]
The result is the same as using the vector function, so, feel free to use the best way in the context. Vectors can be of nested types too, so don’t feel locked to only one type:
But different from its cousin, cons only accept one argument.
A brief of Immutability
Did you notice that I used the term “new vector” while referring to the return value of the function? The reason that I used this term is because Clojure always will return a new vector, and not the same vector with one more item as some people (depending of the language that you come from) may expect.
The proof is simple, let’s bind a vector to an identifier, use conj to add something, and print the vector again:
Note how the our-vector doesn’t change, Clojure always returns a new vector and you can expect this behavior for almost anything while coding Clojure, immutability is one of the pillars of Clojure. In future post I’ll talk only about immutability and it advantages, but for now this is whats matters.
OMG! These structures are strong like a rock!
If we want to use the value you can bind it to a net identifier:
Back to talk about functions that you can use with vectors, other nice function is the nth that returns the value the value in the given index (0-indexed):
=> our-vector
[1 2 3]
=> (nth our-vector 1)
2
Just to finish about vector, let’s talk about first/rest functions, just as you imagine, first will return the value at index 0 of your vector:
And we have our rest function, that will return a new sequence will all values except the first of our vector:
=> (rest our-new-vector)
(42 "Hello World" 23)
And I don’t need to say again that the original vector will stay the same, right?
Using the first/rest functions we can access any value of our vector just using recursion, but if you just want to access the last value, you can use last of course.
=> (last our-new-vector)
23
I think that we know everything to get started working with vectors, now let’s talk a bit about lists.
List
I already talked a little about the list in my post about syntax, but basically, everything in Clojure is a list (If you don’t know about what I’m talking check the post and you’ll understand), if a list is what we use in almost everything in Clojure, let’s take a look on how we can use lists.
To create a list just put your data around parentheses , just like it:
(1 2 42)
But if you try to create a list in this way, it will raise an error like we talked in our previous post. Clojure will try to execute this list as code and will expect a function in the first value of the list, so, if we want to really use a list we need to tell Clojure to not execute this value, and we do this appending an apostrophe to the beginning of our list:
=> '(1 2 42)
( 1 2 42)
Another amazing thing about the list is that the count, first, rest, last, nth, cons works equal as you learned on vectors (and we’ll learn why soon), so, don’t need to learn again! But different from vector, if you use conj it will append to begging of the list.
=> (conj '(1 2 3 4) 5)
(5 1 2 3 4)
Just like vectors if you don’t want to create with the literal, you can use a function to do this job for you.
=> (list 1 2 42)
(1 2 42)
Have you noticed that you use a list to create another list?
[IMAGEM FUNNY]
Maps
It’s impossible to imagine programming nowadays without maps, or as some languages call “Hashes”, its the simplest, fastest and elegant way to represent real world structured data, in functional programming it gains more attention, because is probably the best way to do that.
To create a new map in Clojure, just as the other structures we have two ways, the function, and the syntax sugar, let’s start with the sugar way:
Just put your data inside a curly brackets and have a fun, but pay attention that it need to follow the “key and value” order and if you don’t put a even number it will crash.
To create the same map, you can use the function hash-map:
How we are getting used, we have many ways to do things in Clojure, and I promise that this is the last way that I’ll teach how access data from map in this post:
We have a few ways to access data from a map, and feel free to use the way that you think is better, but particularly I like the first way, passing the keyword and the map.
If we don’t want to pass default values and just know if the key exists in the map, we can use the contains? function:
=> (contains? {:name "otavio"} :name)
true
As you may imagine we can create nested maps two, just putting a new map on a key:
And to access data inside nested maps, is easy, just access the keys in the right order to get the data:
=> (:city (:address person))
:london
When dealing with maps we have the basic set of functions to deal with our data, the first the the assoc that we can use to add values to map, or edit.
It’s important to remember now that almost everything in Clojure is immutable, and maps are immutable, every operation that we are doing on our maps are always returning a newer one.
We can obtain all values or all keys from a map, using the vals and keys function:
And we can merge maps into one just using the merge function, we can pass many maps as we want and remember that if two or more maps have the same key, it will use the value from the rightmost map passed to the function.
Now we know enough about maps, and we already learned a lot about vectors and lists, now it’s time to learn a little bit about how to do things with our collections.
Sequences, the magic behind collections
When dealing with our collection we have common functions that we can use (As we saw with cons or first in this post for example), one great example is the first function:
Other nice option would be use an if statement to select how to take the first item of each collection, but it didn’t sound escalable if we have tons of collection in our language right?
Clojure has a more elegant way to solve this problem and it’s through abstractions, did you realized that sometimes in this posts I said that some function return a sequence? For example, if I call cons on on a vector, it will not return a new vector, it will return a sequence, take a look:
=> (cons 5 [1 2 3 4])
(5 1 2 3 4)
It can looks like a list, but its a sequence, I promise!
const like many other functions of Clojure will work if you pass any data structure that implements the sequence interface. To implement a sequence interface and be a seq the data structure need to respond to three function: first, rest and cons.
If one data structure respond to these functions this structure are called seqable by Clojurists, when can call the seq function on it and it will return a sequence:
=> (seq [1 2 3 4])
(1 2 3 4)
“seq” a new magic!!!
seq transforms our structure in a new sequential structure that behaves like a list, a function like first only expect that you pass a structure that implements that interface, so it call seq on every structure that you pass, and perform the operation.
Sequence Functions
Sequences brings a great power to Clojure, and if a collection is seqable a rich set of functions can be used, and fortunately all data structures that we learned in this posts, are “seqables”, and we can use all these functions!
We already learned few of them, like first, rest, cons, last but the true magic stands on functions that can make processes in our collection, like, map, reduce, filter and many others (Depending of your previous experience you’re already used to some of them).
Map
map is an ambiguous term in Clojure, because it represent the data structure the we saw (commonly called hash in other languages) and it also represent a common function that can be used on sequences. When talking about the function, it’s used when you want to create a new sequence by applying a function for each element of our sequence.
Imagine that we have a vector with maps, and each map represent a person:
In this example we passed the function :name to map apply it for each item of our sequence and return a new sequence with the results of each function (:name) call.
Let’s get the names from map
It’s important to note that functions that operates on sequences, returns a new sequence, so if we want a vector again, we can use the into function (other common seq function) to put the items of our sequence inside a empty vector:
When we learn about functions we will use map it a lot, and you’ll see the true magic behind it.
For
Other common seq function is the for which is very similar to what we see in other languages, it loop through our collection binding the current value to some identifier, the same operation of our last example using for will looks like:
In this example we tell Clojure to loop through our collection person and bind each value to a identifier p, and after that call :name on p.
But let’s try to avoid using for for everything, its much more elegant and functional minded to use functions like map, reduce to do the things, mostly we can use them to solve our problem.
Reduce
The last function that we’ll see in this post is reduce, we will pass a function and a sequence to it too, just like map, but different from map the response of each function will be given as argument to the next one and at the end of our sequence, it returns the result. It sounds a little confusing while reading but it’s simple, the easiest example is use a reduce to obtain the sum of all elements in a vector:
=> (reduce + [26 23 05 42 19 100 120 123])
458
Reduce working
We can give a staring value if we want too and second argument:
(reduce + 10 [26 23 05 42 19 100 120 123])
468
Know how to use reduce correctly can be very powerful and we’ll see this in a future post, but now its enought.
Much more
We’ve a lot of functions to interact with our sequences, but I don’t want to take a deep view in each of them, so, I pretty recommend to read this post and learn other functions if you want, or wait to learn while having a fun with Clojure.
Off: What’s the difference between vectors and lists?
After reading this post a lot of questions come to mind, but the most frequent one can be: “What’s the difference between vectors and lists? Both look the same for me!”, the two structs look the same at first view but behind the scenes both are different.
The difference is simple, and for most people (except me) will remember college days, vectors are equal vectors of other languages, it is a sequential chunk of memory allocated (Did u Remember how to use malloc?), and lists are implemented like a linked list behind scenes.
Lists and Vectors under under the magnifying glass
This difference between each implementation creates advantages and disadvantages for each one, for example, add a new value to a list is simple, the language only needs to create a new “node” and add it to the end or beginning of the list, but add a new value in a vector we need to relocate the chunk of memory and them add the new value.
Otherwise, if you want to access a value from your vector, it will be faster, it only needs to calculate some arithmetic and access, a linked list will need to transverse all the list calling the next node, and it will take a while. (if you want a good post with nice benchmarks with time, check this post)
Both structures look similar but are different on an x-ray, both have its disadvantages and advantages, so you need to know where to use each one.
Conclusions
This is not a short read but of course, we learned a lot, now we know how to use Clojure data structures, the dream of immutability, and the magic of sequences.
We are progressing on our journey of becoming Clojure Wizards.
On next post we’ll talk about functions, high order functions, parameters, and much more.
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!
Simulating RAM in Clojure – Incredible post talking about how to simulate a RAM memory from scratch, the author uses only NAND gates (Yes, the post starts the implementation from the logical gates), and uses almost 14K of NAND gates to implement a 256 bytes ram memory. This post is good for those who love to read something that mix computer architecture and programming.
De Programmatica Ipsum, Issue #25 Smalltalk – Certainly one of my best discoveries of the year is that publication. In this issue, they talk about Smalltalk, its history, and its impact on computer history. As a Rubyist, I fell in love while reading about Smalltalk and I recommend it. Three fabulous posts, but if you only have time for one, I recommend this post.
The open source paradox – Have you noticed that usually developers spend more energy on their side open-source projects than its job?
MISC
Computer Scientists Break Traveling Salesperson Record – Travelling Salesperson is one of the most famous problem of computer science and for many years its best solution was never changed until now, this post talks about who has discovered a new way of solve this problem, and how the new solution works.
Carbon-Aware Kubernetes – This post talks about how you can change Kubernetes scheduler rules to deploy pods in different regions based on carbon-intensity of them. Making your application more carbon-aware.
A Brief Guide to OTP in Elixir – When I learned Elixir the two things that make me fall in love were Supervisors and GenServers, this post explains both in a simple and starter way.
Raft, Understandable Distributed Con – Want to learn Raft in a simple and dynamically way? It can help you, an animated explanation with short texts, perfect for those who want to understand a little bit better how raft consensus algorithm works.
You Don’t Have to Use Docker Anymore – The title is a little bit biased, but I loved the text, it brings nice tools to work with containers and compete with Docker! Podman looks promising.
Buttery Smooth Emacs – Unfortunately I think you’ll need Facebook to read this post, but it’s very interesting to read about how emacs words and about some design decisions around it.
Performance testing the JIT compiler for the BEAM VM – BEAM VM (The VM behind Erlang and Elixir) has shipped its JIT compiler and this post benchmark it using RabbitMQ (A huge application written in Erlang), and the results are amazing. It also takes a brief view of a new tool called perf.
A Short Story About SQL’s Biggest Rival – Do you know that in the early days SQL has a rival? This post is the kind of historical post that I put on every edition of this newsletter, it talks about the history of SQL vs QUEL, we already know who won this fight, but its nice to read.