Richard Miles
Jul 29 · 7 min read

Writing music and programming are basically the same thing, and I am going to prove this to you.

Let’s take the example of functional programming in JavaScript and compare this to percussion notation.

Let’s do some coding

From a programming side, one of the fundamental goals of writing good code is efficient list manipulation — which in the case of JavaScript is usually an array or list of “things” (usually an object of some kind).

We have an array of person objects:

const people = [
{
name: 'Ed',
age: 29,
gender: 'M'
},
{
name: 'James',
age: 30,
gender: 'M'
},
{
name: 'Saskia',
age: 31,
gender: 'F'
},
]

Look familiar? Awesome.

We usually use our programming skills do some kind of mapping or filtering e.g. Make all the names uppercase —

const makeAllCaps = (person) =>  ({ ...person, name: person.name.toUpperCase()})

We then want to run our code to make sure it works —

console.log(people.map(makeAllCaps))

At a very simple level this can be described as:

  • data — what we want to manipulate (people array)
  • functionality — how we want to manipulate it (makeAllCaps function)
  • view — seeing the result in action (console.log and calling the map function on our array of people).

The result would be as follows:

[ { name: 'ED', age: 29, gender: 'M' },
{ name: 'JAMES', age: 30, gender: 'M' },
{ name: 'SASKIA', age: 31, gender: 'F' } ]

One input, one output

In the spirit of functional programming we could look at the above “how” (functionality) part of our example as “pure” in nature. e.g we don’t care about where the people array comes from, and we don’t really care how its output (console.log) — as long as the makeAllCaps function works as expected. For writing music we don’t care too much about who is playing this or what medium it is used to play on — as long as it fits the basic input / output parameters we have defined.

With this being said, we could divide a musical ensemble into a “what”, “how” and “result” paradigm pretty easily.

The what aspect would be the instrument (or ensemble of instruments) — and in the same way we expect our people object to have a name attribute. We expect our instrument to have a particular note (or in our case drum).

Lets make some music

I want to write a piece of music in a rock style, so I assuming the “what” in this case will be a rock drum kit — or at least has all the components required for a simple rock drum kit.

Let’s stick to 4 drums to make this work.

  1. Kick drum
Sits on the bottom line
  1. Snare drum
Sits on the third line from the bottom
  1. Hi-hat
Marked as an “x” and sits at the top
  1. Rest — yes the rest is also part of the music (its basically like the programming equivalent of null)
Weird squiggle that sits in the middle (this rest is a quarter note rest, not all rest notes look the same).

I guess the best way to think of each of these is as an ENUM

We are going to be passing this ENUM data into a function for list manipulation — which in our music example I will call a “bar”, or a single iteration in the list.

In music we need to know how big the items within our list will be, which we’ll call a “time signature”.

4/4

Before we even begin running our program we know that our list can only be 4 items long, with each item being the size of 4 quarter notes (we will be covering what a quarter note is).

Musical note division and how defining time is like type definition

In music we need to be pretty specific when it comes to each iteration (similarly to strongly typed languages such as C++, Java or TypeScript).

However, in music we have multidimensional lists, which can be as big as we want, as long as they fit into the definition specified in our time signature (if you can fit 1000 notes into a single second of music time that is completely acceptable — but not advisable).

Which in the above example (4/4) is 4 quarter notes.

A full note or “whole note” would be an entire iteration through our list, and would look like this —

Whole note

Half of our list would be a “half note”

Half note

A quarter of our list would be a “quarter note”

Quarter note

An eighth of our list would be an “eighth note”

Eighth note

This can keep diving by halving values in our list(16, 32, 64 e.t.c)

So technically, if we have a time signature of 4/4 that means the length of our array / list can be anything that adds up to 4 quarters, 2 halves,1 whole or 8 eighth notes.

Something like this would not work (e.g. this is not valid music) —

Should equal to 4 quarters, but instead looks like 5 quarters

You will never see anything like this is any type of music (even if the composer is trying to be edgy), because music is like programming, and if you try run this, you will get an error.

Something like this, however, would work —

This is valid music (note the time signature of 5/4)

As would this:

2 Eighth notes + 3 quarter notes = 4 quarters

Because we need to define the size of each iteration or bar, music is probably closer to TypeScript than JavaScript because of the strict definitions required in the form of interfaces.

Can we turn music into code?

Let’s take the following 2 bars of music and see if we can turn this into some loosely based TypeScript:

Let’s begin by defining our time signature as well as the notes available within it:

enum Time {
Whole = 1,
Half = 0.5,
Quarter = 0.25,
Eighth = 0.125
}

Next we want to define what type of drums (sounds) we have available to us:

enum Drum {
kick = 'kick',
snare = 'snare',
hihat = 'hihat',
rest = 'rest'
}

When we play on a specific beat we want to know which drum is played, as well as the duration of the note:

interface Note {
time: Time; // see Time enum
drum: Drum;
}

Let’s group these into bars, a bar will contain the number of beats, the duration of each note (duration), as well as the actual music, which in this case is a list of notes:

interface Bar {
beats: number;
duration: Time;
music: Note[];
}

Next, lets define what our music actually looks like — this also falls into the how part of the equation:

const music: Bar[]  = [
{
beats: 4,
duration: Time.Quarter,
music: [
{
time: Time.Quarter,
drum: Drum.kick
},
{
time: Time.Quarter,
drum: Drum.kick
} ,
{
time: Time.Quarter,
drum: Drum.snare
} ,
{
time: Time.Quarter,
drum: Drum.snare
}
]
},
{
beats: 4,
duration: Time.Quarter,
music: [
{
time: Time.Eighth,
drum: Drum.kick
},
{
time: Time.Eighth,
drum: Drum.kick
} ,
{
time: Time.Quarter,
drum: Drum.hihat
} ,
{
time: Time.Quarter,
drum: Drum.rest
}
]
}
]

The main difference between the musical and programatic “how” is that our music is declarative in nature (it is almost impossible to move away from this), while our functional program is procedural in nature, because of this music is probably closer to a markup language such as xml or html with strict type definitions than it is to JavaScript.

Finally, we iterate through our bars and log out the result in an attempt to “play” the music:

const playMusic = (bar: Bar) => {
bar.music.forEach(note => {
console.log(note)
});
}
music.forEach(playMusic)

The result would look something like this:

{ time: 4, drum: 'kick' }
{ time: 4, drum: 'kick' }
{ time: 4, drum: 'snare' }
{ time: 4, drum: 'snare' }
{ time: 8, drum: 'kick' }
{ time: 8, drum: 'kick' }
{ time: 4, drum: 'hihat' }
{ time: 4, drum: 'rest' }

This is would likely be the result part of our equation, and in the spirit of the above conversion on purity — not something we really care about for the scope of this article.

If we had some kind of output that was able to interpret the “note” (length of note) and “drum” (sound clip) results into a realtime sound player we could actually play the music we wrote.

If we wanted to be really fancy we could also write some validation functionality to make sure our notes do indeed fit correctly into our bars e.t.c

Conclusion

There is obviously a lot more to this than what we have discussed above, and while ultimately there are many differences between the two, I would love to see more cross pollination between music and code.

I would love to hear some of your thoughts below as whether or not I have convinced you that writing music is in fact a form of programming, as well as if you have any other examples or thoughts to share.

NONA

We are a leading software development studio focussing on Fintech, Blockchain and Logistics. Contact: studio@nona.digital

Richard Miles

Written by

Full-stack Developer

NONA

NONA

We are a leading software development studio focussing on Fintech, Blockchain and Logistics. Contact: studio@nona.digital

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade