# 4.2

## Immutability

In the Value section, we learned that a value in Elm is anything that can be produced as a result of a computation. We also learned that Elm values are immutable, which means once created, we can never change them. Once again, Elm has borrowed this concept of immutability from mathematics. For example, the number `3` in mathematics is a value that cannot be changed. Sure, we can add or subtract other numbers from it, but `3` itself will never change. If we add `1` to `3`, we get `4` — a completely new number. This is exactly what happens when we try to modify a value, such as a list, in Elm.

### Immutable Constants

All constants in Elm are immutable. Once assigned, a constant cannot be reassigned a different value in the same scope. If you are coming to Elm from an imperative language this might sound confusing. In those languages, it’s common to write code like this:

It means assign `x` as a name to an expression that evaluates to `1`. Then take the current value of `x`, add `1` to it and assign the result back to `x` essentially mutating its original value. Let’s try that same code in Elm to see what happens.

As usual, Elm provides a descriptive error message pointing out that it doesn’t allow mutation. Definitions like `x = x + 1` are not allowed in both algebra and Elm because we already defined `x` as `1` and now we are saying that `x` is `2`. It can’t be both at the same time.

If you pay close attention to the error message, Elm is actually trying to tell us why it can’t allow mutation in this case. When we try to evaluate an expression such as `x = x + 1`, we’re asking Elm to create a constant named `x` that is defined in terms of itself. So Elm will try to expand the definition further as shown below creating an infinite loop:

Recursive Definition
`x = x + 1`
`x = (x + 1) + 1`
`x = ((x + 1) + 1) + 1`
`x = (((x + 1) + 1) + 1) + 1`
`x = ((((x + 1) + 1) + 1) + 1) + 1`
`...`

Elm also tells us that we can fix this by giving the `x + 1` expression a new name like this:

In an imperative language, `x` is appropriately called a variable because its value can vary even after its creation. Whereas in Elm, `x` is a constant. Because Elm doesn’t allow mutation, the language has no variables. Does this mean we can’t use the same name to represent other values anywhere else in our code? Not really. Once assigned, a constant cannot be reassigned to a different value only in the same scope.

Constants like `x` are local to their scope so their life is usually short. When their scope is no longer alive, they will be discarded. After that we can reuse the name to represent other values. The function definition shown below is a good example of a constant in a limited scope. Go ahead and add it right above `main` in `Playground.elm`.

Now call `multiplyByFive` from `main`.

Run `elm reactor` from the `beginning-elm` directory in terminal if it’s not running already and go to `http://localhost:8000/src/Playground.elm` in a browser. You should see `15`.

We learned in chapter 3 that `let` expression is one of the ways we can create a local scope in Elm. The `multiplier` constant in `multiplyByFive` function above is bound to `5`. As soon as the program execution steps out of the `let` expression, `multiplier` won’t be alive anymore. If we try to reassign a different value to it inside the `let` expression Elm will complain. Replace the `multiplyByFive` function definition in `Playground.elm` with the following code.

Refresh the page at `http://localhost:8000/src/Playground.elm` and you should see the following error.

Let’s move the second definition of `multiplier` out of the `multiplyByFive` function and see what happens.

Refresh the page at `http://localhost:8000/src/Playground.elm` once again and you should see a different error.

Shadowing occurs when a constant defined within a certain scope has the same name as a constant defined in a outer scope. It often makes code hard to read and may create unnecessary bugs. Most programming languages allow shadowing by default, but Elm doesn’t. It’s not surprising because two things Elm cares a lot about are minimizing bugs and easy-to-read code. You can read more about shadowing here.

Let’s rename the `multiplier` constant in outer scope to `outerMultiplier`.

Now, if you refresh the page at `http://localhost:8000/src/Playground.elm` once more, the error should be gone and you should see `15` again. Next, let’s try the same thing in `elm repl`.

Hmm… why does the repl allow us to reassign a different value to `multiplier`? That’s because the repl works a little differently. Whenever we assign a different value to an existing constant, the repl rebinds the constant to a new value. The rebinding process kills the constant and brings it back to life as if the constant was never pointing to any other value before. Without this rebinding process, it would be difficult to try things out in the repl.

### Immutable Collections

In the Modifying Tuples section, when we were trying to understand why we couldn’t modify tuples, we discovered that all collections in Elm are also immutable. Because it’s hard to build anything useful if we can’t transform data from one form to another, Elm uses a clever technique to give us the appearance of adding or removing values from a collection.

In the example above, we used the `::` operator to add `0` to the beginning of the `numbers` list and used the `drop` function to remove the first element from the same list. Although we were able to add and drop values from the list, its original content has remained intact.

Elm created a copy of the original list, added `0` to it, and returned it as the result. While this was all happening, the original list remained unchanged.

Quote: “In a purely functional program, the value of a [constant] never changes, and yet, it changes all the time! A paradox!” - Joel Spolsky

### Performance Implications of Immutability

Creating a new copy of data whenever we update it sounds like an expensive operation from performance standpoint. This is a valid concern. However, Elm is smart and it knows the existing data is immutable. So it reuses it, in part or as a whole, when building new data. Consequently, immutability doesn’t really incur any performance penalty in Elm. Here is how the internal representation of the new list from the example above looks:

### Benefits of Immutability

We have talked a lot about how constants and values are immutable in Elm, but what benefits do we get from it? The primary benefit of immutability is that it allows us to write programs that behave as expected. This leads to highly maintainable code. To make this more concrete, let’s compare an implementation in Elm with another language that doesn’t have immutability baked in. JavaScript fits the bill.

Back in the Sorting a List section, we learned how to sort a list containing the top seven highest scores (shown below) from regular season games in NBA history in different orders.

Let’s say the NBA has decided to allow a new performance-enhancing drug that has the potential to double each player’s scoring. This will make it hard to compare current players against players who have already retired, so we need to adjust all historical stats. Let’s write a function to do that. We will first write it in JavaScript — a language that allows mutation — to find out what could go wrong.

Note: Don’t worry if you have never used JavaScript before. The example below is quite simple and you should be able to follow along without any difficulty.

Create a new file called `experiment.js` in the `beginning-elm` directory and add the code below to it.

• `highestScores` — A variable that points to a list of highest scores.

• `scoreMultiplier` — A variable that points to a number used to multiply each element in the `highestScores` list.

• `doubleScores` — A function that takes a list of scores; iterates through each element in the list using a `for` loop; and multiplies them by a value held in the `scoreMultiplier` variable.

Next, load `experiment.js` in `index.html`, which is also located inside the `beginning-elm` directory.

Note: As mentioned in the Elm Compiler section, it’s perfectly fine to use both Elm and JavaScript code side by side.

Open `index.html` in a browser and then go to the browser console.

Opening browser console
Instructions for opening the browser console depends on which browser you’re using. Please read this nice tutorial from WickedlySmart to learn how to open the console on various browsers.

Verify that the code in `experiment.js` is loaded successfully by printing the following values from the console.

Let’s see `doubleScores` function in action. Call it from the console like this:

So far everything looks good. Now let’s go ahead and redefine the `scoreMultiplier` variable in `experiment.js` so that it points to `3` instead.

Notice the original definition `var scoreMultiplier = 2;` is still there. Reload `index.html` in the browser so our changes to `experiment.js` will take effect. After that, apply the `doubleScores` function to the `highestScores` list by typing the code below into the browser console.

`doubleScores` now triples each element in the `highestScores` list. This is problematic. The new behavior does not match its name. We want it to double the scores no matter what, so that other people reading our code aren’t confused by the mismatch.

Unfortunately, most languages that allow mutation suffer from this problem. It’s especially frustrating when the redefinition happens in a remote part of the code, which is hard to detect. At least in the example above, we can see that `scoreMultiplier` is being redefined close to the original definition and we can correct it. But in the real world, most problems caused by mutation tend to manifest after the code has been deployed to a production environment.

How does Elm deal with this situation? Well, let’s reimplement the code above in Elm to find out. Add the following code right above `main` in `Playground.elm`.

Refresh the page at `http://localhost:8000/src/Playground.elm` and you should see the following error.

It’s exactly the same error we got in the Immutable Constants section above. Elm doesn’t allow us to redefine `scoreMultiplier` in the same scope. Remove the second definition of `scoreMultiplier` from `Playground.elm`.

#### Mutation

The JavaScript code above has one more issue: it mutates the original `highestScores` list. Reload `index.html` in browser and enter the following code in console.

As you can see the values inside the `highestScores` list have changed. This is also problematic. To understand why, let’s remove the redefinition `var scoreMultiplier = 3` from `experiment.js` and add two new functions below the `doubleScores` function like this:

As its name suggests, the `scoresLessThan320` function returns all scores that are less than `320`. It delegates the task of checking whether a score is less than `320` or not to the `isLessThan320` function. Reload `index.html` in browser and call the `scoresLessThan320` function from console like this:

`scoresLessThan320` gives us what we expect. But what will happen if we apply the `doubleScores` function before `scoresLessThan320`? To find out let’s reload `index.html` in browser one more time so that we’re starting fresh. After that, apply the functions as shown below in console.

`scoresLessThan320` reports that there are no scores below `320`, which is incorrect. This is because `doubleScores` doubled the values and saved them back into the original list which we ended up passing to `scoresLessThan320` without realizing that it has already been changed.

#### How to Avoid Mutation?

Can this problem be avoided in JavaScript? Absolutely. Replace the current implementation of `doubleScores` in `experiment.js` with this:

`doubleScores` doesn’t modify the existing list anymore. Instead it always returns a new one. Refresh the browser and call `doubleScores` and `scoresLessThan320` in the same order as before.

Now it works as expected. Let’s try this in Elm to see if we will get different results depending on which order we call the `scoresLessThan320` function. Add the following definitions right above `main` in `Playground.elm`

To properly compare the results from JavaScript and Elm, we need to load the code from `Playground.elm` into `elm repl`. Before we do that though, we need to expose some values from the `Playground` module. Modify the first line in `Playground.elm` to this:

Note: We’ll discuss the syntax for exposing valus from a module in detail later in the Creating a Module section.

Now we’re ready to import the `Playground` module in `elm repl`.

We exposed `doubleScores`, `highestScores`, and `scoresLessThan320` so that we don’t have to prefix the module name when we use them. Not having prefix makes it easier to compare our Elm code with the JavaScript code listed above. As mentioned in the Strings section, be careful not to run into name collision when exposing values like this.

One other thing we need to keep in mind is that the `Playground.elm` file must be located inside the `src` directory. Otherwise, `elm repl` won’t know about it because in the `elm.json` file we have specified `src` as the only source directory.

Let’s say we decided to move `Playground.elm` to a new directory called `code`. Now we’ll have to include `code` in `source-directories` as shown below, otherwise the repl won’t find it.

Now let’s apply `scoresLessThan320` before `doubleScores` and see what we get.

We get what we expect. Now let’s apply `scoresLessThan320` after `doubleScores`.

Again, we get what we expect. No matter which order we apply the functions in, we get the exact same result. In Elm, we don’t need to implement `scoresLessThan320` in a special way for it to behave consistently.

Although we were able to resolve the issue introduced by mutation in JavaScript by explicitly returning a new list, we had to be cognizant of the fact that immutability isn’t baked into JavaScript. That made us take extra precaution. This can get tiresome as the code base grows. However, in Elm `List.map` (and all other functions in the `List` module) always return a new list by default. Having immutability baked into the language itself allows us to completely avoid problems like these.