Tal Brenev
August 18, 2020

A while ago, I started working on a little side
project: a grapher for functions of
complex numbers. The first iteration of this project was written in JavaScript.
The implementation was, in hindsight, pretty bad: inelegant, ugly, and most
importantly, difficult to maintain. This was partially because of a lack of
programming experience on my part, ~~and partially because JavaScript is a
horrible, unintuitive abomination of a language~~. A few years later, I learned
about Clojure, and my mind was blown. That’s when I decided to completely
scrap my JavaScript project, and rewrite the entire thing in ClojureScript.

Needless to say, I am much happier with the code quality of the rewritten
project. Sure, part of this can be attributed to the fact that I became a
better coder after a few more years of experience. But I think a huge factor
was the Clojure language itself. The functional, data-oriented style makes you
think about problems in a completely different (and of course, beneficial) way.
And then there’s the many built-in features of Clojure, that allowed me to
solve problems in ways far more elegant than was ever possible in JavaScript.
Here, I’m going to describe how I used one feature which I think is
particularly neat: *protocols*.

Before I talk about what Clojure protocols are and how I used them, I’ll have to back up a bit and talk about the problem that they solved. And to do that, I’ll have to take you back to math class, and talk about complex numbers. If you already know what they are, you should skip ahead to the next section.

To avoid delving too deep into the mathematics, I’ll keep this brief, albeit
slightly inaccurate. There’s a number called , which is equal to
. Yes, you read that correctly: that’s a square root of a negative
number. This might not make a whole lot of sense, but just roll with it. We
call multiples of *imaginary numbers*. , , and
are all examples of imaginary numbers. On the other hand, the numbers you are
familiar with from high school, like , , and , are called
*real numbers*. Finally, if we take an imaginary number and add it to a real
number, we get a *complex number*. For example, is a complex
number. In general, we express a complex number as , which is called
*Cartesian form*. Here, is called the *real part* of the complex number,
and is called the *imaginary part*.

It’s important to note that *every real number is also a complex number*! Every
real number is actually equal to .

Much like real numbers, we can perform arithmetic on complex numbers. Some laws of complex arithmetic are actually quite simple. For example, given two complex numbers and , their sum is simply .

The rule for multiplication, however, is not so simple. To write it down in a
sane way, we need an alternative way of expressing complex numbers, called
*polar form*:

is called the *magnitude*, and is called the *argument*. Don’t
worry about how this works exactly; just know that we can always convert
between Cartesian form and polar form with these formulas:

Given two complex numbers in polar form, and , their product is .

It is possible to perform any other arithmetic operation on complex numbers, including division and exponentiation. You can even calculate the sine and cosine of a complex number, or the logarithm of a complex number. However, these operations are a lot more complex (pun intended), so I won’t go into detail about them here.

Back to the realm of programming. For my project, I needed to implement a
complex arithmetic library. First of all, I needed a way to store complex
numbers; in other words, I needed to create a complex number *type*. In my
JavaScript implementation, I used an object prototype. Here’s a snippet of it:

```
function Complex(real, imaginary) {
this.re = real;
this.im = imaginary;
// ...
}
```

The prototype also had methods for computing the argument and magnitude of a complex number. As it turns out, every other operation can be computed using only the real part, imaginary part, argument, and magnitude. So I decided to not have any more methods in the prototype, and wrote a function for every arithmetic operation I needed. Here’s the function for addition:

```
function Add(c1, c2) {
return new Complex(c1.re + c2.re, c1.im + c2.im);
}
```

The function takes in two instances of `Complex`

, and spits out an instance of
`Complex`

. However, what if I want to pass in a JavaScript `number`

as one of
the parameters instead? After all, every real number is a complex number, so I
should be able to add together a `number`

and a `Complex`

. One way to solve
this would be to check the parameter types at runtime, and dynamically execute
different logic based on those types. However, this would force me to tediously
write several implementations of every single operation. Instead, I opted for
the (still tedious) solution of wrapping every single number I needed in
boilerplate:

```
const compE = new Complex(Math.E, 0);
const comp1 = new Complex(1, 0);
const comp2 = new Complex(2, 0);
const compPi = new Complex(Math.PI, 0);
// ...
```

This is garbage. What we *really* want is to extend the built-in `number`

type:
if it had methods which returned a `number`

’s real part, imaginary part,
argument, and magnitude, we would be able to pass in a `number`

to the complex
arithmetic functions without any additional effort.

Extending built-in types *is* possible in JavaScript. This technique is known
by the less-than-flattering name of “monkey patching”, and is generally frowned
upon. It is not idiomatic, and can lead to tangible issues (for example, two
components monkey patching the same function).

This situation is an example of the *expression problem*: how can we design our
software in such a way that we can easily extend an interface, as well as
easily add new types which implement that interface? The JavaScript language is
not at all helpful in solving this problem. Although there is a way to solve
the expression problem in
JavaScript, it is neither idiomatic
nor elegant.

Enter Clojure protocols: an idiomatic, elegant way of solving this problem. Let’s see how I used them in my project.

A protocol is essentially an interface. It consists of a list of method signatures: the method names, and the parameters that they take in. Types can then provide concrete implementations of those methods. In my project, I created a protocol for complex arithmetic:

```
(defprotocol ComplexArithmetic "Perform the basic arithmetic of the complex numbers."
(re [this] "The real part of the complex number.")
(im [this] "The imaginary part of the complex number.")
(arg [this] "The argument of the complex number, in radians.")
(mag [this] "The magnitude of the complex number."))
```

This protocol defines an interface with four methods: `re`

, `im`

, `arg`

, and
`mag`

.

The next step was to create a concrete type, which will eventually implement
the methods in this interface. One way of doing this in Clojure is using
*records*, which are sort of like structs: they are a collection of fields,
each of which has a value. I created a `ComplexNumber`

record, with two fields,
`real`

and `imaginary`

, which store the real part and imaginary part of the
complex number, respectively.

```
(defrecord ComplexNumber [real imaginary])
(defn complex-from-cartesian [real imaginary]
"Create a complex number by specifying cartesian coordinates."
(->ComplexNumber real imaginary))
(defn complex-from-polar [argument magnitude]
"Create a complex number by specifying polar coordinates."
(->ComplexNumber (* magnitude (Math/cos argument))
(* magnitude (Math/sin argument))))
```

Below the record definition are two “constructor” functions, which are used to
create instances of `ComplexNumber`

. Their purpose is to completely abstract
away the internal details of `ComplexNumber`

.

Now, we need to make the `ComplexNumber`

record implement the interface defined
in `ComplexArithmetic`

. In Clojure, we can do this using `extend-type`

:

```
(extend-type ComplexNumber
ComplexArithmetic
(re [this]
(:real this))
(im [this]
(:imaginary this))
(arg [this]
(Math/atan2 (im this) (re this)))
(mag [this]
(Math/sqrt (+ (Math/pow (re this) 2)
(Math/pow (im this) 2)))))
```

Here, we defined an implementation for each of the methods laid out in the
`ComplexArithmetic`

protocol. `re`

and `im`

simply pass along the values of
the `real`

and `imaginary`

fields. `arg`

and `mag`

are computed using the
formulas which I described above.

We can now get to implementing the operations of complex arithmetic! Here’s how addition and multiplication are implemented:

```
(defn add [x y] "Adds the given complex numbers together."
(complex-from-cartesian (+ (re x) (re y))
(+ (im x) (im y))))
(defn mul [x y] "Multiplies the given complex numbers together."
(complex-from-polar (+ (arg x) (arg y))
(* (mag x) (mag y))))
```

Note that `x`

and `y`

don’t have to be instances of `ComplexNumber`

: they can
be any type, as long as that type implements the interface defined in
`ComplexArithmetic`

.

And now for the best part. We want to extend the built-in type `number`

, so
that it also implements `ComplexArithmetic`

. We can do this with `extend-type`

as well:

```
(extend-type number
ComplexArithmetic
(re [this]
this)
(im [this]
0)
(arg [this]
0)
(mag [this]
this))
```

And that’s it! We can now add a `number`

and a `ComplexNumber`

; the following
line of code, which adds and , is completely valid:

```
(add 5 (complex-from-cartesian 1 2))
```