# 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 illegal 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 essentially 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.

Scope
A scope is a region in a program where defined constants exist and are accessible. Constants created in a region cannot be accessed outside of that region. As soon as the program execution leaves this region all constants and values created in the region will be destroyed.

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 apply `multiplyByFive` in `main`.

If you don’t have `elm-reactor` running already, run it from the `beginning-elm` directory in the terminal. After that go to `http://localhost:8000/elm-examples/Playground.elm` on your browser and you should see `15` rendered on the screen.

As we learned in the Let Expression section, `let` expression is one of the ways we can create a local scope in Elm. The `multiplier` constant in `multiplyByFive` function 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.

If you refresh the page at `http://localhost:8000/elm-examples/Playground.elm`, you should see the following error.

But if we move the second definition of `multiplier` out of the `multiplyByFive` function, Elm doesn’t complain anymore because it’s now defined in a different scope than the one that resides in the `let` expression.

If you refresh the page `http://localhost:8000/elm-examples/Playground.elm`, the error should be gone and you should see `15` rendered on the screen. Go ahead and remove the `multiplier = 6` definition. Now let’s try the same thing in the 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 reassign a different value to an existing constant, the repl essentially 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.

“In a purely functional program, the value of a variable 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 that existing data is immutable. So it reuses it, in part or as a whole, when building new data. As a result, 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 like:

### 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, for example JavaScript, that doesn’t have immutability baked in.

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.

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 root project directory `beginning-elm`.

Now add the following code to it.

`scores` - A variable that points to a list of highest scores.

`multiplier` - A variable that points to a number that will be used to multiply each element in the `scores` 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 `multiplier` variable.

Next, load `experiment.js` in `index.html` located in the root project directory `beginning-elm` like this:

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

Open `index.html` in a browser and then open 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 that explains 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. Apply it like this in the console.

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

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

`doubleScores` now triples each element in the `scores` list. This is problematic. Its new behavior does not match its name. We want it to only 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 `multiplier` 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`.

If you refresh the page at `http://localhost:8000/elm-examples/Playground.elm`, 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 `multiplier` in the same scope. Go ahead and remove the redefinition `multiplier = 3`.

The JavaScript code above has one more issue: it mutates the original `scores` list.

As you can see the values inside the `scores` list have changed. This is also problematic. To understand why, let’s remove the redefinition `var multiplier = 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 the browser so that the new code in `experiment.js` will get loaded. After that apply the `scoresLessThan320` function in the browser 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 the browser one more time so that we’re starting fresh. After that apply the functions as shown below in the browser 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 been changed from underneath.

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

`doubleScores` doesn’t modify the existing list anymore. Instead it always returns a new one. Refresh the browser and apply the `doubleScores` and `scoresLessThan320` functions 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 apply the `scoresLessThan320` function. Add the following definitions right above `main` in `Playground.elm`

To properly compare the results from the experiment we conducted with JavaScript code in the browser console with the Elm code, we need to load the code in `Playground.elm` into `elm-repl`. Currently, Elm looks for modules only in the `beginning-elm` directory because in the `elm-package.json` file we have specified `"."` as the only source directory. `"."` means the directory where `elm-package.json` itself is located which happens to be `beginning-elm`. For `elm-repl` to find `Playground.elm`, we need to add `elm-examples` to the list as well.

Don’t forget to add a comma after `"."`. From the repl, load the `Playground` module.

We exposed `scores`, `doubleScores`, and `scoresLessThan320` so that we don’t have to prefix them with 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 functions and values like this. Now let’s apply `scoresLessThan320` before `doubleScores` and see what we get.

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

Again, we get what we expect. We don’t need to implement `scoresLessThan320` in a special way in Elm 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.