Functions in Clojure: Day 4

Abid Uzair
Clojure Days
Published in
3 min readDec 9, 2017

Let me tell you briefly about special forms and macro calls which are known as expressions just like function calls.

Special forms unlike function calls do not evaluate all of their operands. Best example of special form is if statement.

user=> (if India-wins-cricket-match
then-i-will-party
or-i-will-applaud-the-opposition)

In the above form, either of the two operands will be evaluated hence if is considered to be a special form.

How special forms are different from regular functions:

  • Unlike function calls, they don’t evaluate all the operands
  • They cannot be passed as arguments to functions
  • Special forms implement core Clojure functionality that just can’t be implemented with functions(Not really sure what that means!)

What are Macros ? They are similar to special forms in that they evaluate their operands differently from function calls, and they also can’t be passed as arguments to functions, more on this later.

Let’s learn how to define functions in Clojure. Here’s an example:

(defn make-it-double
"doubles the number passed in the argument"
[number]
(* 2 number))
user=> (make-it-double 13)
;; 26

There are 5 main parts:

  1. defn : starts with the keyword
  2. make-it-double : function name.
  3. doubles the number passed in the argument : :doc-string which describes about the function. Helpful when you’re generating documentation of your code. You can view the docstring for a function in the REPL with (doc function-name)
  4. [number] : Argument. A function can be passed 0 or more arguments. Number of arguments is the function’s arity.
  5. (* 2 number) : This is the function body. It returns the double of the number passed as argument. It can have multiple forms, but the last form is returned by the function.

Let us look into a concept called Arity Overloading, which I find really interesting. It means that a different function body will be executed based on the arity (number of arguments). Here’s a simple example:

(defn your-bio
([name]
(str "My name is " name ". I love Clojure!"))
([]
(your-bio "Unknown")))
user=> (your-bio "Abid Uzair")
;; "My name is Abid Uzair. I love Clojure!"
user=> (your-bio)
;; "My name is Unknown. I love Clojure!"

Next up, let us learn about rest parameters( & )This lets you to handle variable arity functions. As the name suggests, you can simply put rest of the parameters into a list.

(defn fav-places [country & places]
(str "In " country ", must places to visit are "
(clojure.string/join ", " places)))
user=> (fav-places "India" "Taj Mahal" "Kashmir" "Charminar")
;; "In India, must places to visit are Taj Mahal, Kashmir,
;; Charminar"

In the next article, I will be sharing about Destructuring which is a very unique concept you will see in functional programming languages. If there is anything that is mentioned above is not clear, please do let me know in the comment section down below.

Source: Chapter 3 Do Things: A Clojure Crash Course

Thanks for reading!

I ❤️Clojure

--

--

Abid Uzair
Clojure Days

Currently empowering the person closest to me. Long term plan is to bend the universe for good. Kinda like changing the world one person at a time.