Calling functions

The classic approach of learning a new language is to start with syntax, data types, arithmetics and other primitives. In contrast, we will start with functions and pick up the necessary data-related components as we go.

This is how to call a function in Clojure:

(range 10)

The word range is the function's name, and 10 is the argument. Clojure is a dialect of LISP. All its structures are so-called S-expressions. Sometimes they are also called forms. Everything is wrapped in parens: function calls, function definitions, conditionals, loops, etc.

range is a function from clojure.core, which, essentially, means that it's built in and comes with the language. When called with a single argument, range returns a lazy sequence of numbers from 0 to the passed value, exclusively. (We'll talk about laziness later. Not, not because I'm lazy. I mean, not just because of that…)

To demonstrate a running Clojure code, we'll be using a REPL β€” an interactive shell-like interface to your Clojure programs. REPL stands for "Read, Evaluate, Print, Loop". The easiest way to play with Clojure code and a REPL is to open a REPL.it session.

At some point you should install Clojure locally (you need to install Java JDK first). Once installed, run clj in the console. REPL.it website is handy, but your local environment will be faster and more comfortable to work with. Also, REPL.it's behavior makes it somewhat hard to quickly type in the Clojure REPL.

We can see that the sequence is another S-expression, which looks indistinguishable from a function call, as if 0 was a function's name, followed by nine numeric arguments. Keep this in mind, we'll get back to this mystery later.

Functions in Clojure may have different arities β€” the amount of parameters. range has 4 arities: 0, 1, 2 and 3. Here are non-zero arities demonstrated. Try to guess what 2nd and 3rd arguments mean:

user=> (range 10)
(0 1 2 3 4 5 6 7 8 9)

user=> (range 3 10)
(3 4 5 6 7 8 9)

user=> (range 3 10 2)
(3 5 7 9)

user=> (range 3 10 3)
(3 6 9)

When there's one argument, it corresponds to the end value. When there are two arguments, they correspond to start and end. The third argument specifies step amount. If you open documentation about range, you'll see this:

Usage: (range)
       (range end)
       (range start end)
       (range start end step)

Returns a lazy seq of nums from start (inclusive) to end
(exclusive), by step, where start defaults to 0, step to 1, 
and end to infinity. When step is equal to 0, returns an 
infinite sequence of start. When start is equal to end, 
returns empty list.

Everything in Clojure is an expression, so you can pass things around. Let's call another function and pass the result of range to it:

user=> (first (range 10))
0

first takes a sequence and returns its first element. There're also second and last:

user=> (second (range 3 14 2))
5

user=> (last (range 3 14 2))
13

To get an arbitrary element, use nth, which takes 2 arguments β€” sequence and index:

user=> (nth (range 3 14 2) 4)
11

In case this feels confusing, here's how the same line of code would've looked in a C-like language:

nth(range(3, 14, 2), 4)

Exercises

Use your local clj, or use the REPL above, or open a new one in a separate window. Feel free to write in the editor itself and push the "play" button, or simply use the dark, interactive panel. You can drag the divider between the editor and interactive panel to resize those areas.

Exercise 1. Call range and pass two arguments to it:

  1. 4
  2. Last value of (34 67 18 299 13)

Of course, the point is not to just put number 13, but retrieve it programmatiaclly.

When creating lists manually, you need to put ' in front of it so that Clojure knows it's a list and not a function call. Example:

(second '(34 67 18 299 13))

Exercise 2. Multiplication and other arithmetic operations in Clojure are just functions +, *, -, /. Call range and pass it one argument:

  1. the multiplication of the second and the last element of (3 2 14 29 8 18 12)

Exercise 3. Call range and pass such arguments so that the returned result is (4 13 22 31 40 49).