That's so Rusty: Mutables
Tags: rust, immutable, functional
Published: 2020-09-06 16:37:07

---
title: That's so Rusty: Mutables
published: true
description: 
tags: rust, immutable, functional
series: rusty
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/j85wu5cd4j1qev9temtz.png
---

Given its unique nature, a lot of people are curious to know if Rust is functional.

![Search query](https://dev-to-uploads.s3.amazonaws.com/i/excbrfe7cj6ibf4to81s.PNG)

Is it? Let's find out.
For a programming language to be considered strictly functional it has to adhere to functional paradigm where functions are first class citizens and shared state, mutable data, and side-effects are not allowed. For that reason, a pure function will always return the same result for the same arguments. Rust supports Object Oriented Programming, which means it allows shared state. That disqualifies it from being a purely functional language. However, it borrows some functional concepts such as immutability. 

All Rust variables are immutable ... by default. 
There are a few ways to mutate them as shown below.

#### 1. Mut keyword

```Rust
fn main()
{
  let mut vec = vec![1, 5, 10, 2, 15];
  println!("The vector is: {:?}", vec);
  vec = vec![16, 2, 7, 5];
  println!("The vector is: {:?}", vec);
}
```
Above, the vector **vec** is declared mutable with the **mut** keyword, making it possible to change its contents.


#### 2. Shadowing

```Rust
fn main()
{  
  let s = String::from("Hello from");
  let s = String::from("A shadow");
}
```
Although it looks like **s** has been mutated, it hasn't. The **let** keyword declares another variable that happens to have the same name as existing one. This declaration overwrites the previous variable, effectively shadowing it.

So, you can still mutate things but it takes some effort. Its natural to think that this is an unnecessary complication but it has its merits that probably outweigh the cons. With default immutability the compiler guarantees that when a value is declared, it won't change; it can be accessed from various contexts and won't be updated. This not only makes code easier to read and write but also eliminates classes of bugs such as race condition and undefined behavior. These bugs rise from the following conditions:

* Two or more pointers access the same data at the same time.
* At least one of the pointers is being used to write to the data.
* Access to the data is not synchronized.

Since we established that all values have exactly one owner in [previous post](https://dev.to/imaculate3/that-s-so-rusty-ownership-493c), what are the ways multiple pointers can access the same data? The answer is borrowing; accessing data without necessarily taking ownership. Borrowing provides references which are similar to C++ pointers.

References are especially useful when passing values to functions. If all functions took ownership of arguments, we'd have to return arguments from the function so that they can be reused in the original scope. The example below illustrates how cumbersome it would be to use a function that calculate the length of a vector.

```Rust
fn main()
{
  let vec = vec![16, 2, 7, 5];
  let (len, vec) = calculate_length_take(vec);
  println!("The vector {:?} has length {}", vec, len);
}

fn calculate_length_take(v : Vec<i32>) -> (usize, Vec<i32>)
{
    println!("Calculating the length of {:?}", v);
    return (v.len(), v);
}

```

The function **calculate_length()** gets a whole lot better with references. We can create a reference that borrows from **vec** and pass it to the function. The function can access the data without moving ownership so the vector remains valid after the function call.


```Rust
fn main()
{
  let vec = vec![16, 2, 7, 5];
  let v_ref = &vec;
  println!("The vector size is {:?}", calculate_length(v_ref));
  println!("The vector is still: {:?}", vec);
}

fn calculate_length(v : &Vec<i32>) -> usize
{
    println!("Calculating the length of {:?}", v);
    return v.len();
}
```

As you might expect, references are immutable by default. Mutable references are allowed as long as they point to mutable data. Mutable references are by definition the perfect recipe for race conditions and bugs. To prevent that, Rust compiler enforces that that at any given scope, there is either one mutable reference or any number of immutable references to the same data. 

For illustration, Let's look at C++ and Rust program that essentially do the same thing: print the smallest number in array of integers. The C++ version below is totally valid, it compiles and runs without warning. 

```C++
#include <iostream>
#include <algorithm>    
#include <vector>
using namespace std;

int smallest_element(int *p)
{
    int size = sizeof(p)/ sizeof(int);
    sort(p, p+size);
    return p[0];
}

int main () {  
  int arr[] = {16, 2, 7, 5};
  cout << "The first element is: " << arr[0] << endl;
  cout << "The smallest element is: " << smallest_element(arr) << endl;
  cout << "The first element is: " << arr[0] << endl;
}
```

The function **smallest_element** looks completely harmless, it simply returns smallest element in the array, but it does so with side-effect of sorting it. Reusing **arr** blindly will result incorrect behavior which will be hard to debug especially if the function is imported from external library.

Let's try translating that to Rust. The snippet below is as close as we can get, you can interactively run it on [Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=94fd8a8474d7493bd92ac73d55406d50).

```Rust
fn main()
{
  let vec = vec![16, 2, 7, 5];
  let vec_ref = &vec;
  println!("The first element is: {:?}", vec_ref[0]);
  let vec_ref_2 = &vec;
  println!("The smallest element is: {:?}", smallest_element(vec_ref_2));
  println!("The first element is: {:?}", vec_ref[0]);
}

fn smallest_element(v : &Vec<i32>) -> i32
{
    v.sort();
    return v[0];
}
```
Does it compile?
 
![Mutable error](https://dev-to-uploads.s3.amazonaws.com/i/wbym0bulv967qjg6rbqo.PNG)

No, but the error message seems straight forward. The vector sort function changes the vector, so requires it to be mutable. Let's see what happens after changing the signature of smallest_element() to take mutable reference instead. 

```Rust
fn smallest_element(v : &mut Vec<i32>) -> i32
{
    v.sort();
    return v[0];
}
```

Is the compiler satisfied?

![Mismatched error](https://dev-to-uploads.s3.amazonaws.com/i/y37xnrytqigpbebha1cj.PNG)

Not yet, but the error message is actionable. Since **smallest_element()** now takes a mutable reference, we can't pass immutable reference. Making **vec_ref_2** mutable, should easily fix it.

```Rust
 let vec_ref_2 = &mut vec;
```

Well, not quite.

![Mutable ref error](https://dev-to-uploads.s3.amazonaws.com/i/52q97iiy92k0is3aql6n.PNG)

Makes sense that we can't have mutable reference to immutable data. The error message recommendations have been pretty spot on so far, making **vec** mutable should get us closer to compilation.

```Rust
  let mut vec = vec![16, 2, 7, 5];
```

Or not.

![Immutable ref error](https://dev-to-uploads.s3.amazonaws.com/i/pw00jkqhy9mam2a2ajka.PNG)

The problem is we are using an immutable reference to data after declaring mutable reference to it. This reference is invalid since the mutable ref may have changed the data; in this case, it did. Since **vec_ref** is unsafe to use, we can work around it by commenting out the last print statement.

```Rust
// println!("The first element is: {:?}", vec_ref[0]);
```

Hooray! A working program finally 🍻.
![Joy](https://dev-to-uploads.s3.amazonaws.com/i/elkq9sk4xxscm3i9rvl5.PNG)

Isn't it nice that we have caught a potentially nasty bug at compile time? Isn't it awesome that we can rely on error messages for guidance? Turns out default immutability is useful afterall. It may take some time to get used to but I'm starting to like the Rusty way.