Newsletter 11 – 02/2021

Featured Posts

On repl-driven programming – Have you ever asked yourself about the difference between Ruby/Python REPL and Lisp/Smalltalk REPL? They’re different, Ruby and Python don’t have interactive programming environment, and this post helps you understand this difference.

What I’ve Learned in 45 Years in the Software Industry – This developer shared what learned in over four decades working with software development, and four of the six most important fundamentals in his opinion are not of technology.

10 years(-ish) of Elixir – Ten years after the first commit on Elixir Repo, Jose Valim (Its creator) talks about the current state of Elixir in many subjects and what is coming.

Reverse Engineering the source code of the BioNTech/Pfizer SARS-CoV-2 Vaccine – This post was hard to read, especially because I don’t know a lot about biology, but is awesome. The post has a lot of good external links to explore too.

FOOD ON THE TABLE WHILE GIVING AWAY CODE – How to deal with open source projects while working to get food on the table, is a topic been discussed a lot in recent days. In this post, Daniel Stenberg the founder of the curl project shares its history and how he is dealing with it.

Rust is a hard way to make a web API – Rust is awesome and we know it. But this post talks about why Rust is not the best language to build a classic web API. It shows good reasons to believe in it.

MISC

I received first-ever donation on my open-source side project and it felt great! – This developer received first ever donation to its open source project, and shared it.

new codebase, who dis? (How to Join a Team and Learn a Codebase) – This post bring nice tips about how to join a team and learns it’s codebase, something that you probably didn’t learn at college.

Ruby 3.0 JIT and beyond – Ruby 3 is 3x faster than Ruby 2, with a great work of its JIT, but it isn’t faster to Rails applications yet, in this post the main contributor of Ruby’s JIT talks about its future.

Stealing Your Private YouTube Videos, One Frame at a Time – A step by step short post talking about how this bug hunter find a bug on youtube to steal private youtube videos.

Securing Your GitHub Project – Security is important for your project, and this post has 15 tips about how to secure your project.

A complete guide to pytest – It seems like s simple thing but can be very useful for those who are starting with Python.

The Next Gen Database Servers Powering Let’s Encrypt – Let’s Encrypt upgraded it’s database server, if you’re courious about its hardware to provide free TLS cert for 235M of websites, you should read it.

Build Your Own Text Editor – A nice tutorial to spend a weekend, building your own text editon in almost 1000 lines of C!

REST Servers in Go: Part 1 – standard library – Series of posts about how to build a REST API in Go. Each post will use a different approach, the first is with standard library, the second using router and the third using a framework.

Maximizing Developer Effectiveness – Let’s talk about developer effectiveness, this post brings a great view about what is being effective and feedback loops. It introduces the concept of micro feedback loops, things that usually don’t have a lot of attention from engineers but can lead to a great gain of productivity.

How Complex Systems Fail – 18 short tips about how complex systems fail.

Clojure Journey VIII – Functions

Functions are a crucial part of every programmer’s day job, when talking about a function, it can be defined as a set of instructions that MUST perform a specific task together and if you want, can be referred under an identifier.

For those who already know the basics of a programming language, it isn’t a new technique, almost all programming languages have some way to create your own functions. Clojure as a functional programming language, has functions on its core (as the name suggests), a software written using it, can be seen as a set of functions that together perform a task.

A function in a beautiful blueprint can be drawn as a magic black box that receives inputs and produces outputs, for example, we have a black box, that we sent 2 and 2 to it, and the output is 4, therefore, we can conclude that inside that box has a mechanism to sum the given x and y:

In Clojure to create a new function, we can use fn, fallowed by its params inside square brackets, and its body when you place your operations.

To create a function that prints a hello with a given name, we just need to type:

=> (fn [name] (println "Hello" name))

Now we have our function, that’s great! But how do we call it?

Using this way we’re creating what are called “anonymous functions” and this name is given because this function doesn’t have a name to be called later, and if we want to use it, we need to evaluate it and pass its arguments.

=> ((fn [name] (println "Hello" name)) "Gabi")
"Hello Gabi"

In that way, Clojure will evaluate our function first, and then call it with our given arguments.

Anonymous function has a short way of be created to, and its using #(), our previous example will look like this in the shorter way:

(#(println "Hello" %) "Gabriela")

Note that our parameter is referred as % inside our anonymous function in that way, if we have more parameters to our function it can be referred as %1, %2%n, and we can use %& to refer to the “rest”.

If we want to bind an anonymous function to an identifier to refer later, we can use the def that we already learned in past posts, to bind our anonymous function to a name.

=> (def say-hello (fn [name] (println "Hello" name)))
#'user/say-hello
(say-hello "Gabriela")
=> "Hello Gabriela"

This is awesome, now we can use our function how many times we want, with different parameters:

=> (say-hello "Otavio")
"Hello Otavio"
=> (say-hello "V")
"Hello V"

Fortunately, to avoid write def fallowed by fn every time, Clojure has defn that will act as a fusion of def and fn that we previous used:

Our say-hello the function will look like this:

=> (defn say-hello [name] (println "Hello" name))
#'user/say-hello
=> (say-hello "Clojure")
"Hello Clojure"

Now we know a new spell that we can use every time that we’re playing with magic! We can write our “black box” function from the first example, like this:

=> (defn sum [x y] (+ x y))
#'user/sum
=> (sum 2 2)
4

Now every time makes sense right?

This example can lead us to another interesting thing in Clojure, a function will always return its last evaluated instruction, what it means? A function will always return something, our sum function (last example) will return the sum of x and y because (+ x y) it’s our last evaluated expression.

Clojure treats its functions as what we call “first-class citizens” and it means that we can return functions from functions, bind it (store at variable), store it at a data structure, and pass functions as an argument to other functions, that’s great right? Too much power to use while creating new spells.

Functions like our sum that always returns the same value for the same arguments is called pure functions, in a beautiful world, it would be the only kind of functions, we always want to work with pure functions because it’s returned value is predictable. Unfortunately, we have the dark side, “impure functions” which is basically a function that can return different values for the same arguments and can return unexpected values.

Let’s take a look at an example, what of these functions can you always preview the value returned?

The first one just multiply two values, with we send it two numbers it will work, for example, if we call it with 2 and 2 it will always return 4, we can always predict its return value and its awesome, we have a pure function.

The second function of the draw, if impure, the function read-line, will take a input from user, and we can’t predict its return value, the user can input anything when asked, and we can’t preview it.

When writing good software is a good architecture pattern to isolate impure functions, so you can correctly handle it, expecting errors and much more.

Function documentation

When writing software is always good to find a balance when your software is correctly documented, Clojure provides a beautiful way to document part of your software with docstrings on function declarations, just add your doc before function parameters, like that:

(defn sum
  "Sum `x` and `y`"
  [x y]
  (+ x y)) 

When we learn more about namespaces we’ll learn how much it can be useful to document public functions.

You can read a function doc with doc spell, just use it with the function name, if its contains doc, it will be displayed:

=> (doc sum)
-------------------------
user/sum
([x y])
  Sum `x` and `y`
nil

When use anonymous functions

Anonymous functions look good, but some people have the question “If I can create a named function and call it everywhere, why should I need it?”, well, it’s a good question. It can be used in a lot of ways, mostly when dealing with functions that returns or receive functions, or in specific cases when you need to write a short function.

The most common example is with map (that we learned how to use in the previous post), sometimes you’ll want to apply a simple function to a sequence and don’t want to create a named function, for example:

=> (map #(str "Hey " % ", how you doin?") 
     ["Otavio" "V" "Gabi"])
("Hey Otavio, how you doin?" "Hey V, how you doin?" 
"Hey Gabi, how you doin?")

Know when to use short anonymous functions is a great skill for a little wizard.

Conclusions

Functions are essential, especially in a functional language, it’s a core feature in almost all programming languages and is a part of every developer day, learn and understand how to use it will be great and will help a lot when developing.

We as Clojure wizards can create a lot of new, useful and powerful spells now.

Next steps

On the next post of this series, we’ll keep talking about functions, but more features around it that can help you a lot.

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!

Follow my blog to get notified every new post: