Warning This is a work-in-progress document which is being made by the author while learning the language from the official documentation and other references on the net. The author hopes it could be useful for somebody, but please make sure to verify its contents with authoritative sources. For error reporting please write to contactos at americati.com.

## Intro

We’ll implement a trivial task: get the average of some of student scores. The usual average is the arithmetic one, given by the usual formula:

`PH = (a + b + ...)/n`

To add a little twist, we’ll also calculate the harmonic average, given by

`PH = n/[1/a + 1/b + ...]`

Which for two elements is reduced to `2ab/(a+b)`.

We’ll use this "problem" in order to implement several possible solutions with Rust.

The highly recommended Rust installation method is via `rustup` (see https://www.rust-lang.org/tools/install.) After installation, a Cargo binary project must be setup:

`diego@dataone:~/devel/RUST\$ cargo new --vcs none xtut`

In the `src` subdirectory there is a `main.rc` program which may be used as starting point. But for this tutorial we’ll create many small standalone examples, which is accomplished by storing the code files in the `src/bin` subdirectory, which must be manually created:

```diego@dataone:~/devel/RUST\$ cargo new --vcs none xtut
diego@dataone:~/devel/RUST\$ cd xtut
diego@dataone:~/devel/RUST/xtut\$ mkdir src/bin```

From now, we’ll work from the `xtut` project’s subdirectory. I’m working in a Linux Xubuntu environment with Rust 1.51, using the `VSCode` IDE (here https://www.youtube.com/watch?v=f6tizikEMTk some instructions for the VSCode setup.)

 Note Originally I’ve used "Corrosion" (Rust plugin for the Eclipse IDE), but found "VSCode + Rust Plugin" to be more responsive, lightweight and less buggy.

## The Solutions

### Trivial implementation

We start using 32-bit-signed-integers (i32) to store the student scores:

``````fn main() {
let x1 = 16;
let x2 = 12;
println!("AVG({},{}) PA={}", x1, x2, pa(x1, x2));
}

fn pa(a: i32, b: i32) -> i32 {
(a + b) / 2
}``````

We build and run with:

``````diego@dataone:~/devel/RUST/xtut\$ cargo run --bin p0010
Compiling xtut v0.1.0 (/home/diego/devel/RUST/xtut)
Finished dev [unoptimized + debuginfo] target(s) in 0.50s
Running `target/debug/p0010`
AVG(16,12) PA=14``````

Obviously, `main` is the starting function (`fn`) of the program, and we defined two integer variables (the type is inferred as i32 by the called function. The `println!` is a macro instruction (recognized by the ending bang) which sends output to the standard output (like C’s `printf`) using `{}` as placeholders for the arguments.

Note that the returned value is the last expression in the function; in the C language we would have to employ:

``return (a + b) / 2;``

Which is also valid in Rust, and mandatory for returning from any non-final location in the function.

 Note This trivial program did produce (in my computer) an executable of about 3.3 megabytes, but there are several (good) reasons for it. Please see https://github.com/johnthagen/min-sized-rust for some ideas to mitigate this situation.
 Note The `println!()` placeholders support a similar syntax as C’s `printf()`, but it is not the same. For more information please see https://doc.rust-lang.org/std/fmt/ .

### Harmonic Average

As shown in the introduction, the harmonic average is the inverse of the arithmetic average of the inverted values; here we blindly apply this concept by reusing the previous arithmetic average function:

``````fn main() {
let x1 = 16;
let x2 = 12;
println!("AVG({},{}) PA={} PH={}", x1, x2, pa(x1, x2), ph(x1, x2));
}

fn pa(a: i32, b: i32) -> i32 {
(a + b) / 2
}

fn ph(a: i32, b: i32) -> i32 {
1 / pa(1 / a, 1 / b)
}``````

The execution obviously crashes (panicks in Rust jargon) because the integer divisions `1 / a` and `1 / b` both return zero (like in a C language version):

```diego@dataone:~/devel/RUST/xtut\$ cargo run --bin p0020
Compiling xtut v0.1.0 (/home/diego/devel/RUST/xtut)
Finished dev [unoptimized + debuginfo] target(s) in 0.47s
Running `target/debug/p0020`
thread 'main' panicked at 'attempt to divide by zero', src/bin/p0020.rs:12:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace```

A "solution" would be to apply the "reduced" formula for two values `2ab/(a+b)`; here we’ll also introduce floating point values in order to avoid the "trucating" behavior of the integer division:

``````fn main() {
let x1 = 16;
let x2 = 12;
println!("AVG({},{}) PA={} PH={}", x1, x2, pa(x1, x2), ph(x1, x2));
}

fn pa(a: i32, b: i32) -> i32 {
(a + b) / 2
}

fn ph(a: i32, b: i32) -> i32 {
let af = a as f64;
let bf = b as f64;
let ans = 2.0 * af * bf / (af + bf);
println!("PH (f64) is {}", ans);
// cast to integer: rounds toward zero
ans as i32
}``````

The `ph()` function converts the scores to double precision floating point values (type `f64`) and makes the arithmetical division avoiding the truncation. We can’t leverage the `pa()` function since it does requiere integer parameters.

Finally, the result is converted to `i32` using the `as` keyword. It works like a C language cast: `return (int)ans;`:

```diego@dataone:~/devel/RUST/xtut\$ cargo run --bin p0030
Compiling xtut v0.1.0 (/home/diego/devel/RUST/xtut)
Finished dev [unoptimized + debuginfo] target(s) in 0.47s
Running `target/debug/p0030`
PH (f64) is 13.714285714285714
AVG(16,12) PA=14 PH=13```

As shown, the final cast is truncating the harmonic average from 13.71.. to 13. In scores, is common practice to round the decimal quantities:

``````fn main() {
let x1 = 16;
let x2 = 12;
println!("AVG({},{}) PA={} PH={}", x1, x2, pa(x1, x2), ph(x1, x2));
}

fn pa(a: i32, b: i32) -> i32 {
(a + b) / 2
}

fn ph(a: i32, b: i32) -> i32 {
let af = a as f64;
let bf = b as f64;
let ans = 2.0 * af * bf / (af + bf);
println!("PH (f64) is {}", ans);
ans.round() as i32
}``````

Now we get:

```diego@dataone:~/devel/RUST/xtut\$ cargo run --bin p0040
Compiling xtut v0.1.0 (/home/diego/devel/RUST/xtut)
Finished dev [unoptimized + debuginfo] target(s) in 0.48s
Running `target/debug/p0040`
PH (f64) is 13.714285714285714
AVG(16,12) PA=14 PH=14```
1. Avoid the truncation of integer division in the arithmetic average function.

### A single call: Tuples

Here we want to extract both averages in a single call. The function parameters are the same (the scores), but how to return two values together?

One way is using a tuple:

``````fn main() {
let x1 = 16;
let x2 = 12;
let proms = pah(x1, x2);
println!("AVG({},{}) PA={} PH={}", x1, x2, proms.0, proms.1);
}

fn pah(a: i32, b: i32) -> (i32, i32) {
let pa = (a + b) / 2;
let af = a as f64;
let bf = b as f64;
let ans = 2.0 * af * bf / (af + bf);
println!("PH (f64) is {}", ans);
let ph = ans.round() as i32;
(pa, ph)
}``````

Note that the tuple components are extracted with the syntax `value.0`, `value.1`, etc.

Instead of a couple of arguments, we could use a single tuple-argument:

``````fn main() {
let x1 = 16;
let x2 = 12;
let args = (x1, x2);
let proms = pah(args);
println!("AVG({},{}) PA={} PH={}", x1, x2, proms.0, proms.1);
}

fn pah(ab: (i32, i32)) -> (i32, i32) {
let pa = (ab.0 + ab.1) / 2;
let af = ab.0 as f64;
let bf = ab.1 as f64;
let ans = 2.0 * af * bf / (af + bf);
println!("PH (f64) is {}", ans);
let ph = ans.round() as i32;
(pa, ph)
}``````

### A more complex data type

The scores will be associated to some course phase which will be named "period". To model this idea, we’ll define a new data type named `SchoolScore` which contains both the period and the achieved score:

``````pub struct SchoolScore {
period: u8,
score: i32,
}

fn main() {
let s1 = SchoolScore {
period: 1,
score: 16,
};
let s2 = SchoolScore {
period: 2,
score: 12,
};
println!("AVG({},{}) ", s1.score, s2.score);
// the first average works!
println!("PA={}", pa(s1, s2));
// but with the second one fails
//println!("PH={}", ph(s1, s2));
}

fn pa(a: SchoolScore, b: SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: SchoolScore, b: SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

Structs are similar to their C language counterparts. As shown, their values are built with the same syntax of their declaration, but replacing the component types with the component values.

Also, the instance components are accessed with the `object.attribute` syntax (like C.) Since the `period` is not used at all, we avoid some ugly warnings at compilation time by adding the optional `#[allow(dead_code)]` directive.

```diego@dataone:~/devel/RUST/xtut\$ cargo run --bin p0060
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/p0060`
AVG(16,12)
PA=14```

As shown, the first call (to the `pa()` function) works as expected; but if we uncomment the second one (to the `ph()` function) we get the following compilation error:

```18 |     println!("PA={}", pa(s1, s2));
|                          -- value moved here
19 |     // but with the second one fails
20 |     println!("PH={}", ph(s1, s2));
|                          ^^ value used here after move```

In this point we got into the first interesting Rust feature: ownership.

#### Ownership

Let’s explain this from the C language perspective: assume we have an object (maybe an struct) dynamically created:

``````struct Dummy *ptr = calloc(1, sizeof(struct Dummy));
some_call(ptr);
....
free(ptr);``````

What if `some_call()` (or any other further called function) does free the pointer? Clearly the second `free()` may crash the program.

Some (most?) programming languages avoid this issue at all by providing an automatic facility for object removal (freeing the memory) called garbage collection. Rust provides the concept of "ownership", corresponding to the program code who is "in charge" of the object removal: it (usually) happens when the containing function or block finishes its execution (the variable gets out of scope.) Again: all the objects created during the program execution have an owning code block (usually a function.) At first, the owner is the block where the object is created, but it may be transfered later.

The problem with the previous program (with the `ph()` call) is that the first call (to the `pa()` function) effectively transfers the ownership of the object handled by `s1` (and `s2`) to the function. The ownership passes to the variable `a` (and `b`.) Those variables are discarded upon function termination (like any local variable), and the handled object is destroyed.

So, when the `main()` function is resumed, both `s1` and `s2` are invalid handlers since the pointed objects are no longer in memory.

Such "ownership transfer" is known as a "move" operation.

Please re-read this section until enlightment :). Next, we’ll see some ways to call `ph()`.

### The Copy trait

But why the previous examples did work? …​ if we look up carefully, the function arguments were of type `i32`. Also, all the primitive numeric types like `i32` implement the so called `Copy` "trait".

 Note A trait is like a Java interface or a C++ abstract class: the instances have a set of methods available. Sometimes, no method is present at all: the trait is used to specify (mark) some behavior of the type.

The `Copy` trait is used by Rust to know when an object is "simple" enough so:

1. When calling a function, the parameters have a complete copy of the object, with its own owership (no "move" operation is performed.) So the caller’s variable continues being valid

2. Each of the object copies is liberated from memory when their handling variable goes out of scope

3. In practice, just a "shallow copy" (bitwise copy) is needed to have a complete object copy of the same data type

 Note For tuples, since the two components were `i32`, i.e. of a Copy type, then the full tuple is considered of Copy type: https://doc.rust-lang.org/std/primitive.tuple.html#trait-implementations-1

Now, our `struct` is composed of primitive types, but Rust does require we to explitly mark it as a Copy. A "fast way" to achieve it is shown in the following listing:

``````// first solution: Copy trait
#[derive(Copy, Clone)]
pub struct SchoolScore {
period: u8,
score: i32,
}

fn main() {
let s1 = SchoolScore {
period: 1,
score: 16,
};
let s2 = SchoolScore {
period: 2,
score: 12,
};
println!("AVG({},{}) ", s1.score, s2.score);
println!("PA={}", pa(s1, s2));
println!("PH={}", ph(s1, s2));
}

fn pa(a: SchoolScore, b: SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: SchoolScore, b: SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

The standard trait implementation syntax will be deferred to further examples. Here we use an "abbreviated form" provided by Rust for some common cases in the `#[derive(…​)]` directive: it instructs the compiler to silently generate a "default" trait implementation which is enough for the simplest cases.

The `Clone` trait is a "supertrait" of `Copy`, so types which implement `Copy` must also implement `Clone`; fortunately, Rust does provide default implementations for both traits, so we are able to implement them with #[derive] directives:

``````#[derive(Copy, Clone)]
pub struct SchoolScore {...}``````

Recapitulating: we have a complex (`struct`) data type which is composed of primitive (Copy) types, so we are signaling the compiler that such complex type is also a Copy type; then we use it as in the previous examples: the object is fully copied when passed between functions.

The following solution will work even if the struct components are not Copy types.

### References

For any type `T`, the type described as `&T` is known as a "shared reference to T". It is an alias for the object which does not entail the move operation, so we may solve our problem with the following listing:

``````// second solution: Immutable (shared) references
pub struct SchoolScore {
period: u8,
score: i32,
}

fn main() {
let s1 = SchoolScore {
period: 1,
score: 16,
};
let s2 = SchoolScore {
period: 2,
score: 12,
};
println!("AVG({},{}) ", s1.score, s2.score);
println!("PA={}", pa(&s1, &s2));
println!("PH={}", ph(&s1, &s2));
}

fn pa(a: &SchoolScore, b: &SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: &SchoolScore, b: &SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

Since `pa()` and `pb()` just get an alias but does not get ownership, the objects are not destroyed until `main()` (the only owner) terminates.

We should understand that this solution and the previous one are not opposed but complementary. Some ideas:

1. The Copy (and Clone) trait is usually implemented for types for which we’re sure no non-Copy component will be added in the future

2. Passing a reference to a function entails passing a memory location (pointer) which imply filling the stack with 4 or 8 bytes

3. Passing a Copy-type object fills the stack with a number of bytes equal to the object size (with some additional padding), so could be expensive for bigger types

The passing of a reference as parameter is known as a "borrow", as opposed with a transfer of the ownership.

### Move again

The following "solution" is shown only for illustrative purposes: the "move" operation happens when calling the `pa()` with both objects, but another "move" does happen when that function does return a tuple which contains the same objects:

``````// third solution: moving in and out
pub struct SchoolScore {
period: u8,
score: i32,
}

fn main() {
let s1 = SchoolScore {
period: 1,
score: 16,
};
let s2 = SchoolScore {
period: 2,
score: 12,
};
println!("AVG({},{}) ", s1.score, s2.score);
let (s1, s2, xpa) = pa(s1, s2); // reusing the s1/s2 identifiers (not mandatory)
println!("PA={}", xpa);
println!("PH={}", ph(s1, s2));
}

fn pa(a: SchoolScore, b: SchoolScore) -> (SchoolScore, SchoolScore, i32) {
let ans = (a.score + b.score) / 2;
(a, b, ans)
}

// weird implementation: get ownership and return the ownership
fn ph(a: SchoolScore, b: SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

The returned tuple components are individually assigned to variables using the following syntax which leverages the Rust’s "pattern matching" feature:

``let (s1, s2, xpa) = pa(s1, s2);``

We reused the names `s1` and `s2`, effectively shadowing the previous variables: it is a feature in Rust that the variable identifiers can be reused as needed.

The ownership of the objects returns to `main()`, allowing the final call to `ph()` with a final "move".

Again, this is only for conceptual demonstration purposes.

### Text Strings

Now we introduce the `String` data type, which is a container for lists of characters, also known as text strings. We’ll change the "period" component’s data type of the `SchoolScore` structure to be a String:

``````pub struct SchoolScore {
period: String,
score: i32,
}

fn main() {
let s1 = SchoolScore {
period: String::from("January"),
score: 16,
};
let s2 = SchoolScore {
period: String::from("February"),
score: 12,
};
println!("AVG({},{}) ", s1.score, s2.score);
println!("PA={}", pa(s1, s2));
// println!("PH={}", ph(s1, s2));
}

fn pa(a: SchoolScore, b: SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: SchoolScore, b: SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

The structure is initialized with a `String` built with the `String::from()` function, which is "associated" to the `String` type, so is known as an "associated function".

Note that a `String` object allows the mutation of the contained text; in this respect is similar to Java’s `StringBuilder`.

As in previous examples, if we uncomment the call to `ph()` we get the familiar "moved" error:

```   Compiling xtut v0.1.0 (/home/diego/devel/RUST/xtut)
error[E0382]: use of moved value: `s1`
--> src/bin/p0100.rs:18:26
|
8  |     let s1 = SchoolScore {
|         -- move occurs because `s1` has type `SchoolScore`, which does not implement the `Copy` trait
...
17 |     println!("PA={}", pa(s1, s2));
|                          -- value moved here
18 |     println!("PH={}", ph(s1, s2));
|                          ^^ value used here after move```

As before, we’ll analyze some possible solutions.

### The Clone trait

A first approach would be to implement the `Copy` trait as in a previous example. This fails because the `period: String` component does not implement the `Copy` trait.

An interesting question is why `String` does not implement such trait? the reason is that ```String`s are essentialy pointers to some memory region where the associated text resides; and as the `Copy``` trait signals Rust to make copies of such pointer (a shallow copy), the result would be a new variable pointing to the same memory region. But a new `String` does need a new associated memory region since it must be able to store different text contents.

So the `String` copy process involves more than a "shallow copy" or "bitwise copy" as provided by `Copy` trait. This scenery is known as a "deep copy", and the `Clone` trait is the associated one.

Unlike the "shallow copy" implied in a function call or variable assignement, the cloning operation needs to be explicitelly requested by the invocation of the trait’s `clone()` method.

Fortunately, `String` already implements the `Clone` trait, so we may use the `#[derive(Clone)]` directive for the structure, which in turn clones the compoments:

``````// first solution with String: Clone trait
#[derive(Clone)]
pub struct SchoolScore {
period: String,
score: i32,
}

fn main() {
let s1 = SchoolScore {
period: String::from("January"),
score: 16,
};
let s2 = SchoolScore {
period: String::from("February"),
score: 12,
};
println!("AVG({},{}) ", s1.score, s2.score);
println!("PA={}", pa(s1.clone(), s2.clone()));
println!("PH={}", ph(s1.clone(), s2.clone()));
}

fn pa(a: SchoolScore, b: SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: SchoolScore, b: SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

### Explicit implementation of the Clone trait

The following alternative version avoids the `#[derive(Clone)]` directive by an explicit implementation of the trait. It is the same result, but we introduce it to show the syntax of for trait implementations:

``````// first solution with String: Clone trait
pub struct SchoolScore {
period: String,
score: i32,
}

impl Clone for SchoolScore {
fn clone(&self) -> Self {
SchoolScore {
period: self.period.clone(),
score: self.score,
}
}
}

fn main() {
let s1 = SchoolScore {
period: String::from("January"),
score: 16,
};
let s2 = SchoolScore {
period: String::from("February"),
score: 12,
};
println!("AVG({},{}) ", s1.score, s2.score);
println!("PA={}", pa(s1.clone(), s2.clone()));
println!("PH={}", ph(s1.clone(), s2.clone()));
}

fn pa(a: SchoolScore, b: SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: SchoolScore, b: SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

The `impl Clone for SchoolScore {…​}` is fairly obvious. As the `Clone` trait has only the `clone()` method, let’s explain its signature:

``fn clone(&self) -> Self {...}``

The `clone()` method does receive a reference to the called object with the `self` keyword (lower case) and its output is an object (not a reference) of the same type of the called object: such type is described by the `Self` keyword (first letter in upper case.)

### Alternative solutions

The introduction of references is straightforward with the addition of the `&` operator:

``````// using references
pub struct SchoolScore {
period: String,
score: i32,
}

fn main() {
let s1 = SchoolScore {
period: String::from("January"),
score: 16,
};
let s2 = SchoolScore {
period: String::from("February"),
score: 12,
};
println!("AVG({},{}) ", s1.score, s2.score);
println!("PA={}", pa(&s1, &s2));
println!("PH={}", ph(&s1, &s2));
}

fn pa(a: &SchoolScore, b: &SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: &SchoolScore, b: &SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

And as in a previous example, we may adapt the "move in, move out" pattern:

``````// moving in and out
pub struct SchoolScore {
period: String,
score: i32,
}

fn main() {
let s1 = SchoolScore {
period: String::from("January"),
score: 16,
};
let s2 = SchoolScore {
period: String::from("February"),
score: 12,
};
println!("AVG({},{}) ", s1.score, s2.score);
let (s1, s2, xpa) = pa(s1, s2); // reusing the s1/s2 identifiers (not mandatory)
println!("PA={}", xpa);
println!("PH={}", ph(s1, s2));
}

fn pa(a: SchoolScore, b: SchoolScore) -> (SchoolScore, SchoolScore, i32) {
let ans = (a.score + b.score) / 2;
(a, b, ans)
}

// weird implementation: get ownership and return the ownership
fn ph(a: SchoolScore, b: SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

### Text Constants

The following dummy program shows a dummy handling of a text constant extracted from a `String`; we explicitly added the variable’s data types for better understanding:

``````fn main() {
let start: String = String::from("some text");
let k: &str;
k = start.as_str();
xtest(k);
}

// no return value
fn xtest(s: &str) {
println!("text is {}", s);
}``````

The expected output:

```diego@dataone:~/devel/RUST/xtut\$ cargo run --bin p0100
Compiling xtut v0.1.0 (/home/diego/devel/RUST/xtut)
Finished dev [unoptimized + debuginfo] target(s) in 0.49s
Running `target/debug/p0100`
text is some text```

The `str` (String slice) is a Rust built-in data type used to reference a range of characters (like a text constant.) In database terminology, it may be considered a "view" to some (section of) a text. In general, the str’s text length is only known at runtime, so Rust forces us to always employ a reference (a pointer) to it. For example, changing the type declaration in the previous program:

``    let k: str;``

Generates the message:

`error[E0277]: the size for values of type `str` cannot be known at compilation time`

A simpler version of the previous example involves discarding the `String` at all:

``    let k = "some text";``

That is, literal text constants in the program must also be handled by the `&str` type.

A previous example involved the `SchoolScore` containing a full `period: String` component which is totally copied when the structure is cloned. But if our domain model allows to assume that such text is never changed from the structure-object creation time (i.e. is inmmutable), then we could emply a `&str` reference:

``````pub struct SchoolScore {
period: &str,
score: i32,
}``````

Since `period` is now simply a pointer to an immutable memory region, we could create copies of the structure object by the "shallow copy" mechanism: it’s okay that more than one object’s `period` points to the same region, since it is immutable.

### Copy Trait for a pointer to immutable text

So we add the component of type `&str`, but the compiler rejects it with:

```error[E0106]: missing lifetime specifier
--> src/bin/p0110.rs:7:13
|
7 |     period: &str,
|             ^ expected named lifetime parameter```

To illustrate the problem we’ll analyze a hypotetical version of the program:

``````pub struct SchoolScore {
period: &str,
score: i32,
}

fn main() {
let s1;
// a new block scope
{
let k = String::from("January");
s1 = SchoolScore {
period: k.as_str(),
score: 16,
};
}
println!("S1: {} ", s1.score);
}``````

For illustrative purposes, we created a new "block scope" in which the object owned by `k` is created and destroyed at termination.

The `s1` structure object does contain a reference to the `k` object’s pointed memory region (captured by the `period: k.as_str()` line) inside the internal block. But as soon as the execution exits from it, the `period` component gets invalid as the mentioned memory region is freed (and maybe overwritten.)

More in Rust terms, we say that `k` does not live enough for its usage in `s1`. In simple cases (like a single function body), the compiler has all the information needed to discover this problem, but when function calls are involved then the compiler may ask for more information about the object’s lifetimes.

So, from https://rust-unofficial.github.io/too-many-lists/second-iter.html: "Quite simply, a lifetime is the name of a region (~block/scope) of code somewhere in a program. That’s it. When a reference is tagged with a lifetime, we’re saying that it has to be valid for that entire region."

Returning to the original example, following the compiler suggestion we add a "lifetime parameter" and the compiler is satisfied:

``````// first solution with &str: Copy trait
#[derive(Copy, Clone)]
pub struct SchoolScore<'a> {
period: &'a str,
score: i32,
}

fn main() {
let s1 = SchoolScore {
period: "January",
score: 16,
};
let s2 = SchoolScore {
period: "February",
score: 12,
};
println!("AVG({},{}) ", s1.score, s2.score);
println!("PA={}", pa(s1, s2));
println!("PH={}", ph(s1, s2));
}

fn pa(a: SchoolScore, b: SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: SchoolScore, b: SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

The `SchoolStore` objects have a lifetime named `'a` (indicated by the `<'a>` parameter of the `struct` declaration), and the `period` references have the same lifetime (indicated by the `&'a str` type declaration.) This means that the object pointed by `period` must live at least as the `struct` container object.

Note that this is only needed for references. For example, the previous `String` object was "owned" by the `struct`, so its lifetime is automatically attached to its container.

 Note The `'a`, `'b`, etc. is the Rust convention for lifetime specifications.

### Again passing references

Nothing to comment in the following example:

``````// second solution with &str: Immutable (shared) references
pub struct SchoolScore<'a> {
period: &'a str,
score: i32,
}

fn main() {
let s1 = SchoolScore {
period: "January",
score: 16,
};
let s2 = SchoolScore {
period: "February",
score: 12,
};
println!("AVG({},{}) ", s1.score, s2.score);
println!("PA={}", pa(&s1, &s2));
println!("PH={}", ph(&s1, &s2));
}

fn pa(a: &SchoolScore, b: &SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: &SchoolScore, b: &SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

What if instead of returning a primitive `i32` average score, we want to return a full `SchoolStore` containing the average? for example, a function like:

``fn pa(a: &SchoolScore, b: &SchoolScore) -> SchoolScore {...}``

The compiler rejects with:

```   |
24 | fn pa(a: &SchoolScore, b: &SchoolScore) -> SchoolScore {
|          ------------     ------------     ^^^^^^^^^^^ expected named lifetime parameter
= help: this function's return type contains a borrowed value, but the signature does not
say whether it is borrowed from one of `a`'s 2 lifetimes or one of `b`'s 2 lifetimes
help: consider introducing a named lifetime parameter```

This is because the response does contain a reference whose lifetime is unknown to Rust; the compiler suspects the reference lifetime matches the input parameters', so complains.

So we declare a lifetime parameter in the functions `pa()` and `ph()` used to annotate the return value:

``````// returning an object
pub struct SchoolScore<'a> {
period: &'a str,
score: i32,
}

fn main() {
let s1 = SchoolScore {
period: "January",
score: 16,
};
let s2 = SchoolScore {
period: "February",
score: 12,
};
println!("AVG({},{}) ", s1.score, s2.score);
let xpa = pa(&s1, &s2);
println!("PA={}", xpa.score);
let xph = ph(&s1, &s2);
println!("PH={}", xph.score);
}

fn pa<'a>(a: &SchoolScore, b: &SchoolScore) -> SchoolScore<'a> {
let ans = (a.score + b.score) / 2;
SchoolScore {
period: "PA",
score: ans,
}
}

fn ph<'a>(a: &SchoolScore, b: &SchoolScore) -> SchoolScore<'a> {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
SchoolScore {
period: "PH",
score: ans.round() as i32,
}
}``````

This way the output parameter lifetime is linked to the "dummy" function parameter and is not liked to any of the input parameters since they were not associated to `'a`.

Note that the returned reference (pointing to texts "PA" and "PH") has a lifetime corresponding to the total program execution since they are literal constants in the program text (see below about the static lifetime.) For better undestanding, Rust rejects the following version of `pa()`:

``````fn pa<'a>(a: &SchoolScore, b: &SchoolScore) -> SchoolScore<'a> {
let ans = (a.score + b.score) / 2;
let x = String::from("PA");
SchoolScore {
period: x.as_str(),
score: ans,
}
}``````

with the following message:

```error[E0515]: cannot return value referencing local variable `x`
|
35 | /     SchoolScore {
36 | |         period: x.as_str(),
| |                 - `x` is borrowed here
37 | |         score: ans,
38 | |     }
| |_____^ returns a value referencing data owned by the current function```

The returned reference inside `SchoolScore` is pointing to the text region of variable `x`, which is destroyed upon `pa()` termination.

### Mutability

The following program fails in several ways:

``````pub struct SchoolScore {
period: String,
score: i32,
}

fn main() {
fail0();
fail1();
fail2();
}

fn fail0() {
let n = 45;
n += 1;
println!("number={}", n);
}

fn fail1() {
let k = String::from("April");
k.push_str(" and May");
println!("another period={}", k);
}

fn fail2() {
let s = SchoolScore {
period: String::from("January"),
score: 31,
};
s.period = String::from("February");
s.period.push_str(" and March");
println!("period={} score={}", s.period, s.score);
}``````

The compiler errors were:

```error[E0384]: cannot assign twice to immutable variable `n`
--> src/bin/p0300.rs:14:5
|
13 |     let n = 45;
|         |
|         first assignment to `n`
|         help: make this binding mutable: `mut n`
14 |     n += 1;
|     ^^^^^^ cannot assign twice to immutable variable
error[E0596]: cannot borrow `k` as mutable, as it is not declared as mutable
--> src/bin/p0300.rs:20:5
|
19 |     let k = String::from("April");
|         - help: consider changing this to be mutable: `mut k`
20 |     k.push_str(" and May");
|     ^ cannot borrow as mutable

error[E0594]: cannot assign to `s.period`, as `s` is not declared as mutable
--> src/bin/p0300.rs:29:5
|
25 |     let s = SchoolScore {
|         - help: consider changing this to be mutable: `mut s`
...
29 |     s.period = String::from("February");
|     ^^^^^^^^ cannot assign

error[E0596]: cannot borrow `s.period` as mutable, as `s` is not declared as mutable
--> src/bin/p0300.rs:30:5
|
25 |     let s = SchoolScore {
|         - help: consider changing this to be mutable: `mut s`
...
30 |     s.period.push_str(" and March");
|     ^^^^^^^^ cannot borrow as mutable```

The root problem is that Rust assumes by default that all variables are immutable. For example, being `n` an immutable integer, it is not allowed to increment its value. Note that a new `n` variable may be declared with `let` (even of any other type), but the current one is immutable.

The `String` object `k` is immutable, so calling its `push_str()` method fails because it needs a "mutable reference" (more on this later.)

Finally, the structure members are immutable as the enclosing object, which diallows the reassignement of `period` and the mutation of such `String` for via `push_str()` as noted above.

But all is happiness with mutable variables:

``````pub struct SchoolScore {
period: String,
score: i32,
}

fn main() {
fail0();
fail1();
fail2();
}

fn fail0() {
let mut n = 45;
n += 1;
println!("number={}", n);
}

fn fail1() {
let mut k = String::from("April");
k.push_str(" and May");
println!("another period={}", k);
}

fn fail2() {
let mut s = SchoolScore {
period: String::from("January"),
score: 31,
};
s.period = String::from("February");
s.period.push_str(" and March");
println!("period={} score={}", s.period, s.score);
}``````

The expected results:

```diego@dataone:~/devel/RUST/xtut\$ cargo run --bin p0300
Compiling xtut v0.1.0 (/home/diego/devel/RUST/xtut)
Finished dev [unoptimized + debuginfo] target(s) in 0.73s
Running `target/debug/p0300`
number=46
another period=April and May
period=February and March score=31```

### Mutable References

Since the students were nice people, the teacher wanted to avoid any score less than 14. So previously to the average calculation, the scores are to be "promoted" to be at least 14.

We’ll employ references in our new `promotion()` function, but a shared (immutable) reference will not allow the structure modification, so we need a "mutable reference":

``fn promotion(a: &mut SchoolScore) -> bool {...}``

The function returns whether the score was "promoted" or not; we’ll ignore this return value but here is used to illustrate the built-in data type for boolean values.

In order to call such function with a mutable reference, we need to start from mutable objects (thinking a bit, it would be pointless to be able to create mutable references from immutable objects.) Then the call use a syntax like:

``promotion(&mut s1);``

The complete listing goes now:

``````pub struct SchoolScore<'a> {
period: &'a str,
score: i32,
}

fn main() {
let mut s1 = SchoolScore {
period: "January",
score: 16,
};
let mut s2 = SchoolScore {
period: "February",
score: 12,
};
println!("AVG({},{}) ", s1.score, s2.score);
promotion(&mut s1);
promotion(&mut s2);
println!("PA={}", pa(&s1, &s2));
println!("PH={}", ph(&s1, &s2));
}

fn promotion(a: &mut SchoolScore) -> bool {
if a.score < 14 {
a.score = 14;
true
} else {
false
}
}

fn pa(a: &SchoolScore, b: &SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: &SchoolScore, b: &SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

The results:

```AVG(16,12)
PA=15
PH (f64) is 14.933333333333334
PH=15```

"At any given time, you can have either one mutable reference or any number of immutable references [to a single object]. References must always be valid."

### Traits

Like Java interfaces or C++ abstract classes, Rust’s traits specify some behavior of a type (usualy a `struct`) by declaring a set of functions (methods) the complying type must implement. In the following example, we’ll define two types: our already known `SchoolScore` and the new `WorkerScore`; both represent entities containing the notion of an integer score. So it would be useful to specify a common trait for both types:

``````pub trait Scored {
fn get_score(&self) -> i32;
}``````

So objects of `SchoolScore` and `WorkerScore` will be able to provide a score by a call with the form `object.get_score()`. Note that the `&self` argument represent the instance being called, and is used by the implementations as shown below.

To make the example a bit more interesting, we’ll define another trait for our types, in order to implement the "promotion" behavior previously discused. So we need a trait able to mutate the object, which is achieved by requiring a mutable reference:

``````pub trait Promotable {
fn promote(&mut self) -> bool;
}``````

The following partial listing shows the types, the trait declarations and their implementations. Also, a `main()` method is added for demonstration purposes:

``````pub struct SchoolScore {
period: String,
score: i32,
}

pub struct WorkerScore {
name: String,
points: i32,
}

pub trait Scored {
fn get_score(&self) -> i32;
}

pub trait Promotable {
fn promote(&mut self) -> bool;
}

impl Scored for SchoolScore {
fn get_score(&self) -> i32 {
self.score
}
}

impl Scored for WorkerScore {
fn get_score(&self) -> i32 {
self.points
}
}

impl Promotable for SchoolScore {
fn promote(&mut self) -> bool {
if self.score < 14 {
self.score = 14;
true
} else {
false
}
}
}

impl Promotable for WorkerScore {
fn promote(&mut self) -> bool {
if self.points < 14 {
self.points = 14;
true
} else {
false
}
}
}

fn main() {
let mut s1 = SchoolScore {
period: String::from("January"),
score: 16,
};
let mut s2 = SchoolScore {
period: String::from("February"),
score: 12,
};
println!("Student averages:");
s1.promote();
s2.promote();
println!("PA={}", pa(&s1, &s2));
println!("PH={}", ph(&s1, &s2));

let mut w1 = WorkerScore {
name: String::from("Mike"),
points: 18,
};
let mut w2 = WorkerScore {
name: String::from("Lance"),
points: 8,
};
println!("Worker averages:");
w1.promote();
w2.promote();
println!("PA={}", pa(&w1, &w2));
println!("PH={}", ph(&w1, &w2));

}``````

The `pa()` and `ph()` implementation is not shown (yet.) But we already see that the `promotion()` method is applied to the struct objects thanks to the `Promotable` trait.

### Trait Bounds

Now we’ll complete the previous example. The following listing provides the implementation of the missing functions:

``````fn pa<T: Scored>(a: &T, b: &T) -> i32 {
(a.get_score() + b.get_score()) / 2
}

fn ph<T: Scored>(a: &T, b: &T) -> i32 {
let af = a.get_score() as f64;
let bf = b.get_score() as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

Both functions have a generic type argument `T`, so are able to receive two objects of some unknown type. But the syntax `<T: Scored>` specify a restriction for the type: it must implement the `Scored` trait. It means we are able to call the `get_score()` method for any object of `T` type.

As in previous examples, the function does receive shared references, since it is enough to call `get_score()` by its trait definition.

So this way the `pa()` and `ph()` are implemented in a generic way. As an important implementation detail, the compiler silently generates the corresponding code for all the types implementing the trait (here were two types), so there is no performance penalty at execution time.

Another equivalent syntax for trait bounds:

``````fn pa<T>(a: &T, b: &T) -> i32
where
T: Scored,
{
(a.get_score() + b.get_score()) / 2
}

fn ph<T>(a: &T, b: &T) -> i32
where
T: Scored,
{
let af = a.get_score() as f64;
let bf = b.get_score() as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````
 Note There is a less used syntax for trait bounds using the `impl` keyword where the function parameter specify the trait complying argument: `fn function-name(param: impl trait-name) {…​}`.

A related less efficient implementation is presented in the following listing. Here we defined an "attribute empty" structure `ImplAveraging` which implements the `Averaging` trait with the previous functions. But this trait is generic in `T`, so we implement it for `T=SchoolScore` and `T=WorkerScore`:

``````pub struct SchoolScore {
period: String,
score: i32,
}

pub struct WorkerScore {
name: String,
points: i32,
}

trait Averaging<T> {
fn pa(a: &T, b: &T) -> i32;
fn ph(a: &T, b: &T) -> i32;
fn promote(a: &mut T);
}

struct ImplAveraging;

impl Averaging<SchoolScore> for ImplAveraging {
fn pa(a: &SchoolScore, b: &SchoolScore) -> i32 {
(a.score + b.score) / 2
}
fn ph(a: &SchoolScore, b: &SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}
fn promote(s: &mut SchoolScore) {
if s.score < 14 {
s.score = 14;
}
}
}

impl Averaging<WorkerScore> for ImplAveraging {
fn pa(a: &WorkerScore, b: &WorkerScore) -> i32 {
(a.points + b.points) / 2
}
fn ph(a: &WorkerScore, b: &WorkerScore) -> i32 {
let af = a.points as f64;
let bf = b.points as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}
fn promote(w: &mut WorkerScore) {
if w.points < 14 {
w.points = 14;
}
}
}

fn main() {
let mut s1 = SchoolScore {
period: String::from("January"),
score: 16,
};
let mut s2 = SchoolScore {
period: String::from("February"),
score: 12,
};
println!("Student averages:");
ImplAveraging::promote(&mut s1);
ImplAveraging::promote(&mut s2);
println!("PA={}", ImplAveraging::pa(&s1, &s2));
println!("PH={}", ImplAveraging::ph(&s1, &s2));

let mut w1 = WorkerScore {
name: String::from("Mike"),
points: 18,
};
let mut w2 = WorkerScore {
name: String::from("Lance"),
points: 8,
};
println!("Worker averages:");
ImplAveraging::promote(&mut w1);
ImplAveraging::promote(&mut w2);
println!("PA={}", ImplAveraging::pa(&w1, &w2));
println!("PH={}", ImplAveraging::ph(&w1, &w2));
}``````

### Trait Objects

In the previous example, the averaging function implementations for our two test types was resolved at compilation time by selecting the appropriate function implementation.

In some situations it is not convenient or possible to resolve the call at compilation time, but only at runtime; this "late binding" is implemented by an additional indirection to be resolved at invocation time, adding a (small) time penalty. This is the same situation which happens with C++ virtual methods, and is the default behavior in Java.

In Rust, it is possible to borrow objects with references tied to a trait; these are kwown as "trait objects" and the `&dyn` syntax is used to distinguish them from plain references:

``````fn pa(a: &dyn Scored, b: &dyn Scored) -> i32 {
(a.get_score() + b.get_score()) / 2
}

fn ph(a: &dyn Scored, b: &dyn Scored) -> i32 {
let af = a.get_score() as f64;
let bf = b.get_score() as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

### Supertraits

It is a common pattern to specialize the types requirements by specifying a hierarchy of interfaces or classes. In Rust, traits may be dependent on other traits (or supertraits.)

In the previous example, the `Promotable` trait may be implemented in terms of an improved `Scored` trait, able to read and update the score:

``````pub trait Scored {
fn get_score(&self) -> i32;
fn set_score(&mut self, s: i32);
}``````

The new `Promotable` trait relies on the object being scored:

``````pub trait Promotable: Scored {
fn promote(&mut self) -> bool;``````

With this in place, both `Promotable` implementations may be exactly the same. To avoid code duplication, we’ll write a single "default" trait implementation inside the trait declaration:

``````pub struct SchoolScore {
period: String,
score: i32,
}

pub struct WorkerScore {
name: String,
points: i32,
}

pub trait Scored {
fn get_score(&self) -> i32;
fn set_score(&mut self, s: i32);
}

pub trait Promotable: Scored {
fn promote(&mut self) -> bool {
if self.get_score() < 14 {
self.set_score(14);
true
} else {
false
}
}
}

impl Scored for SchoolScore {
fn get_score(&self) -> i32 {
self.score
}
fn set_score(&mut self, score: i32) {
self.score = score
}
}

impl Scored for WorkerScore {
fn get_score(&self) -> i32 {
self.points
}
fn set_score(&mut self, points: i32) {
self.points = points
}
}

impl Promotable for SchoolScore {}
impl Promotable for WorkerScore {}

fn main() {
let mut s1 = SchoolScore {
period: String::from("January"),
score: 16,
};
let mut s2 = SchoolScore {
period: String::from("February"),
score: 12,
};
println!("Student averages:");
s1.promote();
s2.promote();
println!("PA={}", pa(&s1, &s2));
println!("PH={}", ph(&s1, &s2));

let mut w1 = WorkerScore {
name: String::from("Mike"),
points: 18,
};
let mut w2 = WorkerScore {
name: String::from("Lance"),
points: 8,
};
println!("Worker averages:");
w1.promote();
w2.promote();
println!("PA={}", pa(&w1, &w2));
println!("PH={}", ph(&w1, &w2));
}

fn pa<T: Scored>(a: &T, b: &T) -> i32 {
(a.get_score() + b.get_score()) / 2
}

fn ph<T: Scored>(a: &T, b: &T) -> i32 {
let af = a.get_score() as f64;
let bf = b.get_score() as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

As shown, empty trait implementations of `Promotable` simply inherit the default implementation.

### Associated functions

As in C++/Java, static methods are associated to a type but not to a particular instance. In rust, the corresponding "associated functions" doesn’t have the `self` parameter.

The following program adds an associated function to the `Scored` trait. That method is used to build a new instance of a concrete type:

``fn build(text: &str, value: i32) -> Self;``

Note the usage of the `Self` keyword (upper case) signaling the return value is of some type implementing the trait. It will be invocated in a generic way, for example:

``T::build("PA", val)``

The so built objects will be the new return value for the averaging functions:

``fn pa<T: Scored>(a: &T, b: &T) -> T {...}``

As before, the concrete type for `T` is resolved at compilation time by the analysis of the trait implementing types.

We also added the `duo_promoter()` function to illustrate the passing of mutable references:

``````pub struct SchoolScore {
period: String,
score: i32,
}

pub struct WorkerScore {
name: String,
points: i32,
}

pub trait Scored {
fn get_score(&self) -> i32;
fn set_score(&mut self, s: i32);
fn build(text: &str, value: i32) -> Self;
}

pub trait Promotable: Scored {
fn promote(&mut self) -> bool {
if self.get_score() < 14 {
self.set_score(14);
true
} else {
false
}
}
}

impl Scored for SchoolScore {
fn get_score(&self) -> i32 {
self.score
}
fn set_score(&mut self, score: i32) {
self.score = score
}
fn build(text: &str, value: i32) -> Self {
SchoolScore {
period: String::from(text),
score: value,
}
}
}

impl Scored for WorkerScore {
fn get_score(&self) -> i32 {
self.points
}
fn set_score(&mut self, points: i32) {
self.points = points
}
fn build(text: &str, value: i32) -> Self {
WorkerScore {
name: String::from(text),
points: value,
}
}
}

impl Promotable for SchoolScore {}
impl Promotable for WorkerScore {}

fn main() {
let mut s1 = SchoolScore {
period: String::from("January"),
score: 16,
};
let mut s2 = SchoolScore {
period: String::from("February"),
score: 12,
};
println!("Student averages:");
duo_promoter(&mut s1, &mut s2);
let xpa = pa(&s1, &s2);
println!("{}={}", xpa.period, xpa.get_score());
let xph = ph(&s1, &s2);
println!("{}={}", xph.period, xph.get_score());

let mut w1 = WorkerScore {
name: String::from("Mike"),
points: 18,
};
let mut w2 = WorkerScore {
name: String::from("Lance"),
points: 8,
};
println!("Worker averages:");
duo_promoter(&mut w1, &mut w2);
let xpa = pa(&w1, &w2);
println!("{}={}", xpa.name, xpa.get_score());
let xph = ph(&w1, &w2);
println!("{}={}", xpa.name, xph.get_score());
}

fn duo_promoter<T: Promotable>(a: &mut T, b: &mut T) {
a.promote();
b.promote();
}

fn pa<T: Scored>(a: &T, b: &T) -> T {
let val = (a.get_score() + b.get_score()) / 2;
T::build("PA", val)
}

fn ph<T: Scored>(a: &T, b: &T) -> T {
let af = a.get_score() as f64;
let bf = b.get_score() as f64;
let ans = 2.0 * af * bf / (af + bf);
let val = ans.round() as i32;
T::build("PH", val)
}``````

Let’s retry a previous variant: set the `SchoolScore’s `period` attribute to a string slice:

``period: &str``

This forced us to introduce lifetimes:

``period: &str -> period: &'a str -> SchoolScore<'a> ...``

Now this will impact in the traits. Specifically, the `build()` method does receive a `&str` which is directly used for the `period` attribute, but there is no guarantee that the pointed string survives to the new returned `SchoolScore` object. Note that this was not an issue in the previous implementation, since the `&str` was used (copied) only for the creation of a brand new `String` with their own managed memory.

So the compiler will ask us to introduce lifetimes specifiers and just following its suggestions we came to this listing:

``````pub struct SchoolScore<'a> {
period: &'a str,
score: i32,
}

pub struct WorkerScore {
name: String,
points: i32,
}

pub trait Scored<'a> {
fn get_score(&self) -> i32;
fn set_score(&mut self, s: i32);
fn build(text: &'a str, value: i32) -> Self;
}

pub trait Promotable<'a>: Scored<'a> {
fn promote(&mut self) -> bool {
if self.get_score() < 14 {
self.set_score(14);
true
} else {
false
}
}
}

impl<'a> Scored<'a> for SchoolScore<'a> {
fn get_score(&self) -> i32 {
self.score
}
fn set_score(&mut self, score: i32) {
self.score = score
}
fn build(text: &'a str, value: i32) -> Self {
SchoolScore {
period: text,
score: value,
}
}
}

impl<'a> Scored<'a> for WorkerScore {
fn get_score(&self) -> i32 {
self.points
}
fn set_score(&mut self, points: i32) {
self.points = points
}
fn build(text: &'a str, value: i32) -> Self {
WorkerScore {
name: String::from(text),
points: value,
}
}
}

impl<'a> Promotable<'a> for SchoolScore<'a> {}
impl Promotable<'_> for WorkerScore {}

fn main() {
let mut s1 = SchoolScore {
period: "January",
score: 16,
};
let mut s2 = SchoolScore {
period: "February",
score: 12,
};
println!("Student averages:");
duo_promoter(&mut s1, &mut s2);
let xpa = pa(&s1, &s2);
println!("{}={}", xpa.period, xpa.get_score());
let xph = ph(&s1, &s2);
println!("{}={}", xph.period, xph.get_score());

let mut w1 = WorkerScore {
name: String::from("Mike"),
points: 18,
};
let mut w2 = WorkerScore {
name: String::from("Lance"),
points: 8,
};
println!("Worker averages:");
duo_promoter(&mut w1, &mut w2);
let xpa = pa(&w1, &w2);
println!("{}={}", xpa.name, xpa.get_score());
let xph = ph(&w1, &w2);
println!("{}={}", xpa.name, xph.get_score());
}

fn duo_promoter<'a, T: Promotable<'a>>(a: &mut T, b: &mut T) {
a.promote();
b.promote();
}

fn pa<'a, T: Scored<'a>>(a: &T, b: &T) -> T {
let val = (a.get_score() + b.get_score()) / 2;
T::build("PA", val)
}

fn ph<'a, T: Scored<'a>>(a: &T, b: &T) -> T {
let af = a.get_score() as f64;
let bf = b.get_score() as f64;
let ans = 2.0 * af * bf / (af + bf);
let val = ans.round() as i32;
T::build("PH", val)
}``````

It could be interesting to compare the previous situation with a simplified C program:

``````#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct SchoolScore {
const char *period;
int score;
};

struct SchoolScore build(const char *ptr, int score) {
struct SchoolScore ans;
ans.period = ptr;
ans.score = score;
return ans;
}

int main() {
char *ptr = malloc(100);
printf("period? ");
fgets(ptr, 100, stdin);
ptr[strlen(ptr)-1]='\0';
struct SchoolScore s = build(ptr, 15);
/*free(ptr);
char *xptr = malloc(100);
strcpy(xptr, "hehe");*/
printf("%s -> %d\n", s.period, s.score);
return 0;
}``````

Its execution works as expected:

```period? March
March -> 15```

But uncommenting the commented lines leads to undefined behavior. In my computer the previous memory block was reused:

```period? April
hehe -> 15```

Rust did protect us from destroying the allocated `*ptr` buffer while the structure object was in use.

### The static lifetime

Despite its name, the "static lifetime" is not related to static methods. The `'static` lifetime signals Rust that the associated objects live for the entire program execution.

The most known case are the literal texts placed in the program’s text: their type may be annotated as `&'static str`.

In the previous examples, all the text strings procede from the literal constants in the source code, so a simpler (yet more restricted) version may be obtained by defining the `SchoolScore` structure as:

``````pub struct SchoolScore {
period: &'static str,
score: i32,
}``````

Note that this is not a general solution but a very restricted one: for example, the `period` text can no longer stem from user input, disk files, etc. For more emphasis, from https://doc.rust-lang.org/stable/book/ch10-03-lifetime-syntax.html#the-static-lifetime:

"[…​] before specifying `'static` as the lifetime for a reference, think about whether the reference you have actually lives the entire lifetime of your program or not […​]. Most of the time, the problem results from attempting to create a dangling reference or a mismatch of the available lifetimes. In such cases, the solution is fixing those problems, not specifying the `'static` lifetime."

``````pub struct SchoolScore {
period: &'static str,
score: i32,
}

pub struct WorkerScore {
name: String,
points: i32,
}

pub trait Scored {
fn get_score(&self) -> i32;
fn set_score(&mut self, s: i32);
fn build(text: &'static str, value: i32) -> Self;
}

pub trait Promotable: Scored {
fn promote(&mut self) -> bool {
if self.get_score() < 14 {
self.set_score(14);
true
} else {
false
}
}
}

impl Scored for SchoolScore {
fn get_score(&self) -> i32 {
self.score
}
fn set_score(&mut self, score: i32) {
self.score = score
}
fn build(text: &'static str, value: i32) -> Self {
SchoolScore {
period: text,
score: value,
}
}
}

impl Scored for WorkerScore {
fn get_score(&self) -> i32 {
self.points
}
fn set_score(&mut self, points: i32) {
self.points = points
}
fn build(text: &str, value: i32) -> Self {
WorkerScore {
name: String::from(text),
points: value,
}
}
}

impl Promotable for SchoolScore {}
impl Promotable for WorkerScore {}

fn main() {
let mut s1 = SchoolScore {
period: "January",
score: 16,
};
let mut s2 = SchoolScore {
period: "February",
score: 12,
};
println!("Student averages:");
duo_promoter(&mut s1, &mut s2);
let xpa = pa(&s1, &s2);
println!("{}={}", xpa.period, xpa.get_score());
let xph = ph(&s1, &s2);
println!("{}={}", xph.period, xph.get_score());

let mut w1 = WorkerScore {
name: String::from("Mike"),
points: 18,
};
let mut w2 = WorkerScore {
name: String::from("Lance"),
points: 8,
};
println!("Worker averages:");
duo_promoter(&mut w1, &mut w2);
let xpa = pa(&w1, &w2);
println!("{}={}", xpa.name, xpa.get_score());
let xph = ph(&w1, &w2);
println!("{}={}", xpa.name, xph.get_score());
}

fn duo_promoter<T: Promotable>(a: &mut T, b: &mut T) {
a.promote();
b.promote();
}

fn pa<T: Scored>(a: &T, b: &T) -> T {
let val = (a.get_score() + b.get_score()) / 2;
T::build("PA", val)
}

fn ph<T: Scored>(a: &T, b: &T) -> T {
let af = a.get_score() as f64;
let bf = b.get_score() as f64;
let ans = 2.0 * af * bf / (af + bf);
let val = ans.round() as i32;
T::build("PH", val)
}``````

This behavior of literal text constants is similar in the C programming language; for example, the following listing works as expected (compare with the C example in the previous section):

``````#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct SchoolScore {
const char *period;
int score;
};

struct SchoolScore build(const char *ptr, int score) {
struct SchoolScore ans;
ans.period = ptr;
ans.score = score;
return ans;
}

int main() {
char *ptr = "June";
struct SchoolScore s = build(ptr, 15);
char *xptr = malloc(100);
strcpy(xptr, "hehe");
printf("%s -> %d\n", s.period, s.score);
return 0;
}``````

### More on generic types

Our "library" of averaging functions is restricted to `i32` quantities. We were lucky our scores were given in such unit. Let’s assume our `WorkerScore` struct has a `u32` unit for the score. To make things more interesting, let’s also assume that in the future some (not yet written) type will need to deal with `f64` scores.

A way to implement these requirements is to define a new trait to be satisfied by the scores, involving conversions to/from f64, since we’ll implement all the calculations in double precision floating point values:

``````pub trait ScoreUnit {
fn to_f64(&self) -> f64;
fn from_f64(val: f64) -> Self;
}``````

We will provide implementations of the trait for the types we are interested: `i32`, `u32` and `f64`. It is interesting that Rust allows the implementation of user traits for any built-in type. For example:

``````impl ScoreUnit for i32 {
fn to_f64(&self) -> f64 {
*self as f64
}
fn from_f64(val: f64) -> Self {
val.round() as i32
}
}``````

The only strange item is the `*self` expression, which means "the value pointed by the reference", i.e. the `ScoreUnit` object which in this context is an `i32`. Now the `Scored` trait may be generic:

``pub trait Scored<T> where T: ScoreUnit{...}``

The averaging functions now will be generic in two parameters: the scoring unit (`K`) and the scored entity (`T`), so both types must be declared. For example:

``fn pa<K: ScoreUnit, T: Scored<K>>(a: &T, b: &T) -> T {...}``

Now the full listing. Observe the implementation of the `Promotable` trait:

``````pub struct SchoolScore {
period: String,
score: i32,
}

pub struct WorkerScore {
name: String,
points: u32,
}

pub trait ScoreUnit {
fn to_f64(&self) -> f64;
fn from_f64(val: f64) -> Self;
}

impl ScoreUnit for i32 {
fn to_f64(&self) -> f64 {
*self as f64
}
fn from_f64(val: f64) -> Self {
val.round() as i32
}
}
impl ScoreUnit for u32 {
fn to_f64(&self) -> f64 {
*self as f64
}
fn from_f64(val: f64) -> Self {
val.round() as u32
}
}
impl ScoreUnit for f64 {
fn to_f64(&self) -> f64 {
*self as f64
}
fn from_f64(val: f64) -> Self {
val
}
}

pub trait Scored<T>
where
T: ScoreUnit,
{
fn get_score(&self) -> T;
fn set_score(&mut self, s: T);
fn build(text: &str, value: T) -> Self;
}

pub trait Promotable<T>: Scored<T>
where
T: ScoreUnit,
{
fn promote(&mut self) -> bool {
if self.get_score().to_f64() < 14.0 {
self.set_score(ScoreUnit::from_f64(14.0));
true
} else {
false
}
}
}

impl Scored<i32> for SchoolScore {
fn get_score(&self) -> i32 {
self.score
}
fn set_score(&mut self, score: i32) {
self.score = score
}
fn build(text: &str, value: i32) -> Self {
SchoolScore {
period: String::from(text),
score: value,
}
}
}

impl Scored<u32> for WorkerScore {
fn get_score(&self) -> u32 {
self.points
}
fn set_score(&mut self, points: u32) {
self.points = points
}
fn build(text: &str, value: u32) -> Self {
WorkerScore {
name: String::from(text),
points: value,
}
}
}

impl Promotable<i32> for SchoolScore {}
impl Promotable<u32> for WorkerScore {}

fn main() {
let mut s1 = SchoolScore {
period: String::from("January"),
score: 16,
};
let mut s2 = SchoolScore {
period: String::from("February"),
score: 12,
};
println!("Student averages:");
duo_promoter(&mut s1, &mut s2);
let xpa = pa(&s1, &s2);
println!("{}={}", xpa.period, xpa.get_score());
let xph = ph(&s1, &s2);
println!("{}={}", xph.period, xph.get_score());

let mut w1 = WorkerScore {
name: String::from("Mike"),
points: 18,
};
let mut w2 = WorkerScore {
name: String::from("Lance"),
points: 8,
};
println!("Worker averages:");
duo_promoter(&mut w1, &mut w2);
let xpa = pa(&w1, &w2);
println!("{}={}", xpa.name, xpa.get_score());
let xph = ph(&w1, &w2);
println!("{}={}", xpa.name, xph.get_score());
}

fn duo_promoter<K: ScoreUnit, T: Promotable<K>>(a: &mut T, b: &mut T) {
a.promote();
b.promote();
}

fn pa<K: ScoreUnit, T: Scored<K>>(a: &T, b: &T) -> T {
let val = (a.get_score().to_f64() + b.get_score().to_f64()) / 2.0;
T::build("PA", ScoreUnit::from_f64(val))
}

fn ph<K: ScoreUnit, T: Scored<K>>(a: &T, b: &T) -> T {
let af = a.get_score().to_f64();
let bf = b.get_score().to_f64();
let ans = 2.0 * af * bf / (af + bf);
let val = ScoreUnit::from_f64(ans);
T::build("PH", val)
}``````

#### Associated types

Returning to the averaging functions like:

``fn pa<K: ScoreUnit, T: Scored<K>>(a: &T, b: &T) -> T {...}``

The complexity of this declaration stems from the degree of generalization of the `Scored` trait. But the structure types only implement `Scored` once for its corresponding scoring type:

``````impl Scored<i32> for SchoolScore {...}
impl Scored<u32> for WorkerScore {...}``````

Given the current requirements, we may assume that there is no sense in providing additional trait implementations; i.e. the following would be pointless:

``````impl Scored<SomeOtherType> for SchoolScore {...}
...
impl Scored<AnotherType> for WorkerScore {...}
...``````

If a single trait implementation is required for a type, then we may employ a simpler option using "associated types":

``````pub trait Scored {
type A: ScoreUnit;
fn get_score(&self) -> Self::A;
fn set_score(&mut self, s: Self::A);
fn build(text: &str, value: Self::A) -> Self;
}``````

The `type` keyword replaces the `<T>` generic parameter. The values corresponding to this type are specified with the syntax `Self::T`.

The implementations must resolve the associated type by associating a concrete type (like in this example) or with the help of a generic parameter:

``````impl Scored for SchoolScore {
type A = i32;
fn get_score(&self) -> i32 {
self.score
}
...
}``````

As shown, the associated types have sense where there is a unique relation between an implementing type, and some trait component type. Now the modified program:

``````pub struct SchoolScore {
period: String,
score: i32,
}

pub struct WorkerScore {
name: String,
points: u32,
}

pub trait ScoreUnit {
fn to_f64(&self) -> f64;
fn from_f64(val: f64) -> Self;
}

impl ScoreUnit for i32 {
fn to_f64(&self) -> f64 {
*self as f64
}
fn from_f64(val: f64) -> Self {
val.round() as i32
}
}
impl ScoreUnit for u32 {
fn to_f64(&self) -> f64 {
*self as f64
}
fn from_f64(val: f64) -> Self {
val.round() as u32
}
}
impl ScoreUnit for f64 {
fn to_f64(&self) -> f64 {
*self as f64
}
fn from_f64(val: f64) -> Self {
val
}
}

pub trait Scored {
type A: ScoreUnit;
fn get_score(&self) -> Self::A;
fn set_score(&mut self, s: Self::A);
fn build(text: &str, value: Self::A) -> Self;
}

pub trait Promotable: Scored {
fn promote(&mut self) -> bool {
if self.get_score().to_f64() < 14.0 {
self.set_score(ScoreUnit::from_f64(14.0));
true
} else {
false
}
}
}

impl Scored for SchoolScore {
type A = i32;
fn get_score(&self) -> i32 {
self.score
}
fn set_score(&mut self, score: i32) {
self.score = score
}
fn build(text: &str, value: i32) -> Self {
SchoolScore {
period: String::from(text),
score: value,
}
}
}

impl Scored for WorkerScore {
type A = u32;
fn get_score(&self) -> u32 {
self.points
}
fn set_score(&mut self, points: u32) {
self.points = points
}
fn build(text: &str, value: u32) -> Self {
WorkerScore {
name: String::from(text),
points: value,
}
}
}

impl Promotable for SchoolScore {}
impl Promotable for WorkerScore {}

fn main() {
let mut s1 = SchoolScore {
period: String::from("January"),
score: 16,
};
let mut s2 = SchoolScore {
period: String::from("February"),
score: 12,
};
println!("Student averages:");
duo_promoter(&mut s1, &mut s2);
let xpa = pa(&s1, &s2);
println!("{}={}", xpa.period, xpa.get_score());
let xph = ph(&s1, &s2);
println!("{}={}", xph.period, xph.get_score());

let mut w1 = WorkerScore {
name: String::from("Mike"),
points: 18,
};
let mut w2 = WorkerScore {
name: String::from("Lance"),
points: 8,
};
println!("Worker averages:");
duo_promoter(&mut w1, &mut w2);
let xpa = pa(&w1, &w2);
println!("{}={}", xpa.name, xpa.get_score());
let xph = ph(&w1, &w2);
println!("{}={}", xpa.name, xph.get_score());
}

fn duo_promoter<T: Promotable>(a: &mut T, b: &mut T) {
a.promote();
b.promote();
}

fn pa<T: Scored>(a: &T, b: &T) -> T {
let val = (a.get_score().to_f64() + b.get_score().to_f64()) / 2.0;
T::build("PA", ScoreUnit::from_f64(val))
}

fn ph<T: Scored>(a: &T, b: &T) -> T {
let af = a.get_score().to_f64();
let bf = b.get_score().to_f64();
let ans = 2.0 * af * bf / (af + bf);
let val = ScoreUnit::from_f64(ans);
T::build("PH", val)
}``````

As shown, now the averaging functions returned to a single generic parameter, reducing unnecessary complexity:

``fn pa<T: Scored>(a: &T, b: &T) -> T {...}``

### The `From` trait

The last example could be made in a more "idiomatic" way by leveraging the `From` trait. We may define a new type named `ScoreValue` containing a `f64`, and convesion facilities to translate to/from this new type and the required `i32`, `u32` and `f64`. For example:

``````pub struct ScoreValue {
value: f64,
}

impl From<i32> for ScoreValue {
fn from(item: i32) -> Self {
ScoreValue { value: item as f64 }
}
}
// then we may do:
let i : i32 = 12;
let sval = ScoreValue::from(i); // sval is of ScoreValue type``````

Previously we used extesively this trait when creating `String` objects from literal text constants using `String::from("some text")`.

The `From` trait implies the `Into` trait, so in the previous example, an alternative syntax would be:

``````let i : i32 = 12;
let sval : ScoreValue = i.into(); // sval's type required for disambiguation``````

Note that `From` is not included in the automatically imported types (prelude), so a `use std::convert::From` directive is supplied at the beginning of the listing (this is similar to C++'s `use`, or Java’s `import` directives):

``````use std::convert::From;

pub struct SchoolScore {
period: String,
score: i32,
}

pub struct WorkerScore {
name: String,
points: u32,
}

pub struct ScoreValue {
value: f64,
}

impl From<i32> for ScoreValue {
fn from(item: i32) -> Self {
ScoreValue { value: item as f64 }
}
}

impl From<u32> for ScoreValue {
fn from(item: u32) -> Self {
ScoreValue { value: item as f64 }
}
}

impl From<f64> for ScoreValue {
fn from(item: f64) -> Self {
ScoreValue { value: item }
}
}

impl From<ScoreValue> for i32 {
fn from(item: ScoreValue) -> Self {
item.value.round() as i32
}
}

impl From<ScoreValue> for u32 {
fn from(item: ScoreValue) -> Self {
item.value.round() as u32
}
}

impl From<ScoreValue> for f64 {
fn from(item: ScoreValue) -> Self {
item.value
}
}

pub trait Scored {
fn get_score(&self) -> ScoreValue;
fn set_score(&mut self, s: ScoreValue);
fn build(text: &str, value: ScoreValue) -> Self;
}

pub trait Promotable: Scored {
fn promote(&mut self) -> bool {
// let v64: f64 = self.get_score().into();
let v64 = f64::from(self.get_score());
if v64 < 14.0 {
self.set_score(ScoreValue::from(14.0));
true
} else {
false
}
}
}

impl Scored for SchoolScore {
fn get_score(&self) -> ScoreValue {
ScoreValue::from(self.score)
}
fn set_score(&mut self, score: ScoreValue) {
self.score = score.into()
}
fn build(text: &str, value: ScoreValue) -> Self {
SchoolScore {
period: String::from(text),
score: value.into(),
}
}
}

impl Scored for WorkerScore {
fn get_score(&self) -> ScoreValue {
ScoreValue::from(self.points)
}
fn set_score(&mut self, points: ScoreValue) {
self.points = points.into()
}
fn build(text: &str, value: ScoreValue) -> Self {
WorkerScore {
name: String::from(text),
points: value.into(),
}
}
}

impl Promotable for SchoolScore {}
impl Promotable for WorkerScore {}

fn main() {
let mut s1 = SchoolScore {
period: String::from("January"),
score: 16,
};
let mut s2 = SchoolScore {
period: String::from("February"),
score: 12,
};
println!("Student averages:");
duo_promoter(&mut s1, &mut s2);
let xpa = pa(&s1, &s2);
println!("{}={}", xpa.period, i32::from(xpa.get_score()));
let xph = ph(&s1, &s2);
println!("{}={}", xph.period, i32::from(xph.get_score()));

let mut w1 = WorkerScore {
name: String::from("Mike"),
points: 18,
};
let mut w2 = WorkerScore {
name: String::from("Lance"),
points: 8,
};
println!("Worker averages:");
duo_promoter(&mut w1, &mut w2);
let xpa = pa(&w1, &w2);
println!("{}={}", xpa.name, i32::from(xpa.get_score()));
let xph = ph(&w1, &w2);
println!("{}={}", xpa.name, i32::from(xph.get_score()));
}

fn duo_promoter<T: Promotable>(a: &mut T, b: &mut T) {
a.promote();
b.promote();
}

fn pa<T: Scored>(a: &T, b: &T) -> T {
let val = (f64::from(a.get_score()) + f64::from(b.get_score())) / 2.0;
T::build("PA", ScoreValue::from(val))
}

fn ph<T: Scored>(a: &T, b: &T) -> T {
let af: f64 = a.get_score().into();
let bf: f64 = b.get_score().into();
let ans = 2.0 * af * bf / (af + bf);
let val = ScoreValue::from(ans);
T::build("PH", val)
}``````
1. If the school scores have a range `0-20`, then the `u8` type would be enough for their storage. Implement the required changes for its support

2. The `promote()` implementation function contains the comparison: `if v64 < 14.0 {…​}`. It is bad style to have a parameter value like `14.0` interspersed in the code expressions. Following https://doc.rust-lang.org/stable/rust-by-example/custom_types/constants.html, replace it with a constant defined at the beginning of the program like: `const PROM_THRESHOLD: f64 = 14.0;`

3. The `PROM_THRESHOLD` is a global constant in the program. It is possible to define type-specific constants; see https://doc.rust-lang.org/reference/items/associated-items.html#associated-constants for more information

### Dynamic allocation

The `Box` data type allows the storage of some information in the heap. It is a pointer to some (user provided) data, which is placed in a dynamically allocated memory region.

The allocated memory is automatically freed when the pointer goes out of scope, so it is more like a C++ smart pointer.

The following program Makes use of boxed variables. To make things a bit more interesting, `pa()` will return a numeric score, but `ph()` a boxed object.

``````pub struct SchoolScore {
period: String,
score: i32,
}

fn main() {
let s1 = Box::new(SchoolScore {
period: String::from("January"),
score: 16,
});
let s2 = Box::new(SchoolScore {
period: String::from("February"),
score: 12,
});
println!("AVG({},{}) ", (*s1).score, (*s2).score);
println!("PA={}", pa(&(*s1), &(*s2)));
let xph = ph(&s1, &s2);
println!("PH={}", (*xph).score);
}

fn pa(a: &SchoolScore, b: &SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: &Box<SchoolScore>, b: &Box<SchoolScore>) -> Box<SchoolScore> {
let af = (*a).score as f64;
let bf = (*b).score as f64;
let ans = 2.0 * af * bf / (af + bf);
let ans = ans.round() as i32;
Box::new(SchoolScore {
period: String::from("PH"),
score: ans,
})
}``````

The boxed contained object is extracted with the "de-reference" operator (like in `*s1.score`.) But Rust is smart enough to deduce we want the de-referenced version and the program may be simplified in the following way (as if no Boxing happened at all):

``````pub struct SchoolScore {
period: String,
score: i32,
}

fn main() {
let s1 = Box::new(SchoolScore {
period: String::from("January"),
score: 16,
});
let s2 = Box::new(SchoolScore {
period: String::from("February"),
score: 12,
});
println!("AVG({},{}) ", s1.score, s2.score);
println!("PA={}", pa(&s1, &s2));
let xph = ph(&s1, &s2);
println!("PH={}", xph.score);
}

fn pa(a: &SchoolScore, b: &SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: &SchoolScore, b: &SchoolScore) -> Box<SchoolScore> {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
Box::new(SchoolScore {
period: String::from("PH"),
score: ans.round() as i32,
})
}``````

"Deref coercion works only on types that implement the `Deref` trait. Deref coercion converts such a type into a reference to another type."

### Reading from command line

The following program shows how to read the contents of the `SchoolScore` line to line from standard input:

``````use std::io;
use std::io::Write;

pub struct SchoolScore {
period: String,
score: i32,
}

fn input(prompt: &str, line: &mut String) {
print!("{}", prompt);
io::stdout().flush().unwrap();
line.clear();
}

fn main() {
let mut line = String::new();
println!("First score");
input("Enter period> ", &mut line);
let period1 = String::from(line.trim());
input("Enter score> ", &mut line);
let score1: i32 = line.trim().parse().unwrap();
let s1 = SchoolScore {
period: period1,
score: score1,
};

println!("Second score");
input("Enter period> ", &mut line);
let period2 = String::from(line.trim());
input("Enter score> ", &mut line);
let score2: i32 = line.trim().parse().unwrap();
let s2 = SchoolScore {
period: period2,
score: score2,
};
println!("AVG({},{}) ", s1.score, s2.score);
println!("PA={}", pa(&s1, &s2));
println!("PH={}", ph(&s1, &s2));
}

fn pa(a: &SchoolScore, b: &SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: &SchoolScore, b: &SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

Notable points:

1. The `input()` function displays the message prompt before reading text; we use the `print!` macro (instead of the `println!`) to avoid sending a new line after the text

2. We’re forcing the flushing of the text from the `print!` macro with `Stdout::flush()`

3. The text line is read with `Stdin::read_line()` which requires a mutable reference to a `String`

4. The `flush()`, `read_line()` and `parse()` functions return a `Result` value which is an enumeration expressing whether the operation was or not successful (`Ok` or `Err` variants); see below for more information

5. This `Result` value is internally marked with the `#[must_use]` attribute, so it will generate a warning if not handled by the programmer

6. The `line.clear()` call simply removes the previous contents in the `String` (else `read_line()` would append the input to the previous stored text)

7. The trimmed `String` is converted to an `i32` by the `parse()` function

We "resolve" the `#[must_use]` attribute in the `Result` value by calling the `unwrap()` method, which simply panics on the error case. See also the `expect(msg)` method which also panics on error, but displaying a user provided error message.

Note that the standard library provides several enumerations named `Result` with the same variants. The I/O related functions return `std::io::Result`, but the `parse()` function does return `std::Result`.

1. Replace the `unwrap()` calls with `expect()` and try tu force their failure cases

2. Test what happens when parsing if we avoid the `trim()` call

3. The `input()` function could be simpler if it just return a brand new `String` instead of reusing a single instance; try it!

#### Matching variants

The `Result` type allows a more intelligent handling of the error condition; a usual pattern is to request the user to re-enter a non valid text. This imply a loop in the execution flow, which may be provided by the Rust’s `loop` keyword.

The `loop` keyword has the form `loop { …​ }` and in principle in an "infinite loop", since it requires an explicit interruption for termination: here we simply `return` from the containing function, ending the loop. Another way corresponds to the `break` keyword, which immediatly jumps to the next line after the loop.

As in C or Java, there is also a `continue` keyword which forces an immediate new loop iteration, which was used in the present example.

Returning to the processing of the `Result` value, it is usualy done by pattern matching on its variants, with the `match` facility:

``````match io::Result-value {
io::Result::Ok(value) => some-expression,
io::Result::Err(msg) => some-expression,
}``````

The last variants may be abbreviated with the `_` wildcard. This is similar to the "default case" of the `switch` block in the C programming language. Also, note that the variants `Ok` and `Err` are imported into the prelude:

``````use std::io;
use std::io::Write;

pub struct SchoolScore {
period: String,
score: i32,
}

fn input_string(prompt: &str) -> String {
loop {
print!("{}", prompt);
io::stdout().flush().unwrap();
let mut line = String::new();
match io::stdin().read_line(&mut line) {
Ok(_) => return String::from(line.trim()),
_ => continue,
}
}
}

fn input_number(prompt: &str) -> i32 {
loop {
print!("{}", prompt);
io::stdout().flush().unwrap();
let mut line = String::new();
match io::stdin().read_line(&mut line) {
Ok(_) => (),
_ => continue,
}
match line.trim().parse() {
Ok(val) => return val,
_ => continue,
}
}
}

fn input() -> SchoolScore {
let period = input_string("Enter period> ");
let score = input_number("Enter score> ");
SchoolScore {
period: period,
score: score,
}
}

fn main() {
println!("First score");
let s1 = input();
let s2 = input();
println!("AVG({},{}) ", s1.score, s2.score);
println!("PA={}", pa(&s1, &s2));
println!("PH={}", ph(&s1, &s2));
}

fn pa(a: &SchoolScore, b: &SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: &SchoolScore, b: &SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

### Error handling with `Result`

The `Result` enumeration is used as return value for user functions which may fail for some interesting reason. As shown, its variants are `Ok` for holding a successful result, and `Err` for holding a failure reason.

For more illustation, lets adapt this previous version of the averaging program:

``````fn main() {
let x1 = 16;
let x2 = 12;
println!("AVG({},{}) PA={} PH={}", x1, x2, pa(x1, x2), ph(x1, x2));
}

fn pa(a: i32, b: i32) -> i32 {
(a + b) / 2
}

fn ph(a: i32, b: i32) -> i32 {
let af = a as f64;
let bf = b as f64;
let ans = 2.0 * af * bf / (af + bf);
println!("PH (f64) is {}", ans);
ans.round() as i32
}``````

Here we’ll introduce `Result` for the corresponding return values and a user defined error type `ScoreError`, considering that the scores must be in the range 0-20, and that our harmonic average formula fails when both scores are zero:

``````enum ScoreError {
OutOfRange,
BothZero,
}
fn main() {
let x1 = 16;
//let x2 = 12;
let x2 = -10;
let arith = match pa(x1, x2) {
Ok(x) => x,
_ => panic!("Invalid arguments for pa()"),
};
let harm = match ph(x1, x2) {
Ok(x) => x,
_ => panic!("Invalid arguments for ph()"),
};
println!("AVG({},{}) PA={} PH={}", x1, x2, arith, harm);
}

fn pa(a: i32, b: i32) -> Result<i32, ScoreError> {
if a < 0 || a > 20 || b < 0 || b > 20 {
return Err(ScoreError::OutOfRange);
}
Ok((a + b) / 2)
}

fn ph(a: i32, b: i32) -> Result<i32, ScoreError> {
if a == 0 && b == 0 {
return Err(ScoreError::BothZero);
}
if a < 0 || a > 20 || b < 0 || b > 20 {
return Err(ScoreError::OutOfRange);
}
let af = a as f64;
let bf = b as f64;
let ans = 2.0 * af * bf / (af + bf);
Ok(ans.round() as i32)
}``````

Which purposedly fails this way:

```\$ cargo run --bin p0470
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/p0470`
thread 'main' panicked at 'Invalid arguments for pa()', src/bin/p0470.rs:11:14
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace```

For more information, we may obtain basic information about the error cause by deriving `Debug`:

``````#[derive(Debug)]
enum ScoreError {
OutOfRange,
BothZero,
}
fn main() {
let x1 = 16;
//let x2 = 12;
let x2 = -10;
let arith = match pa(x1, x2) {
Ok(x) => x,
Err(e) => panic!("Error calling pa(): {:?}", e),
};
let harm = match ph(x1, x2) {
Ok(x) => x,
Err(e) => panic!("Error calling ph(): {:?}", e),
};
println!("AVG({},{}) PA={} PH={}", x1, x2, arith, harm);
}``````

which produce:

```\$ cargo run --bin p0472
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/p0472`
thread 'main' panicked at 'Error calling pa(): OutOfRange', src/bin/p0472.rs:12:19
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace```

A more erognomic way to handle those errors may be obtained with the `?` operator, which extract the `Ok()` variant’s value, or simply forwards (like an exception re-throw) the error for the caller to handle it. Here the error is passed to `main()`, whose return value is adapted appropiatedly:

``````#[derive(Debug)]
enum ScoreError {
OutOfRange,
BothZero,
}
fn main() -> Result<(), ScoreError> {
let x1 = 16;
//let x2 = 12;
let x2 = -10;
println!("AVG({},{}) PA={} PH={}", x1, x2, pa(x1, x2)?, ph(x1, x2)?);
Ok(())
}``````

The standard library provides an `std::error::Error` trait which is the conventional super type for the errors in the language. The following version of the program defines an `ScoreError` type implementing the trait: it has `Debug` and `Display` as supertypes so we "derive" the first one, and implement the second one.

The program asks for two numbers, which are captured from the command line. Here two kinds of error may happen: an I/O related error when reading from the standard input, and a "parsing" error when translating the user text into a number. Both are considered as special values of the `ScoreError`, and we preserve their original value as arguments of the enum variants.

Now let’s see the function:

``fn get_number() -> Result<i32, ScoreError> {...}``

It may "fail" because of an I/O error or a parsing error; in both cases we employ the "?" operator to "re-throw" the exception to the caller, but with the `ScoreError` type.

That means that the I/O errors and the parsing errors must be "converted" into the corresponding variants of `ScoreError` when employing the "?" operator.

In order to achieve this conversion we simple implement the `From` trait for those error types:

``````impl From<io::Error> for ScoreError {...}
impl From<num::ParseIntError> for ScoreError {...}``````

Finally, for demonstration purposes we are explicitly displaying the generated error (if it happens) in the `main()` function.

``````use std::error;
use std::fmt;
use std::io;
use std::num;

#[derive(Debug)]
enum ScoreError {
OutOfRange(usize),
BothZero,
IO(io::Error),
Parse(num::ParseIntError),
}

impl error::Error for ScoreError {}

impl fmt::Display for ScoreError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ScoreError::BothZero => write!(f, "Both scores are zero"),
ScoreError::Parse(err) => write!(f, "Invalid number can't be parsed: {}", err),
ScoreError::OutOfRange(par) => write!(f, "Out of range in parameter {}", par),
ScoreError::IO(err) => write!(f, "I/O related error: {}", err),
}
}
}

impl From<io::Error> for ScoreError {
fn from(err: io::Error) -> ScoreError {
ScoreError::IO(err)
}
}

impl From<num::ParseIntError> for ScoreError {
fn from(err: num::ParseIntError) -> ScoreError {
ScoreError::Parse(err)
}
}

fn main() {
if let Err(e) = run() {
println!("Error: {}", e);
}
}

fn run() -> Result<(), ScoreError> {
let x1 = get_number()?;
let x2 = get_number()?;
println!("AVG({},{}) PA={} PH={}", x1, x2, pa(x1, x2)?, ph(x1, x2)?);
Ok(())
}

fn get_number() -> Result<i32, ScoreError> {
let mut buf: String = String::new();
let number = buf.trim().parse::<i32>()?;
Ok(number)
}

fn pa(a: i32, b: i32) -> Result<i32, ScoreError> {
if a < 0 || a > 20 {
return Err(ScoreError::OutOfRange(1));
}
if b < 0 || b > 20 {
return Err(ScoreError::OutOfRange(2));
}
Ok((a + b) / 2)
}

fn ph(a: i32, b: i32) -> Result<i32, ScoreError> {
if a == 0 && b == 0 {
return Err(ScoreError::BothZero);
}
if a < 0 || a > 20 {
return Err(ScoreError::OutOfRange(1));
}
if b < 0 || b > 20 {
return Err(ScoreError::OutOfRange(2));
}
let af = a as f64;
let bf = b as f64;
let ans = 2.0 * af * bf / (af + bf);
Ok(ans.round() as i32)
}``````

The topic of error handling in Rust is not trivial. Please see https://blog.burntsushi.net/rust-error-handling/ for a comprehensive explanation. More ideas may be read in https://doc.rust-lang.org/rust-by-example/error/multiple_error_types.html .

#### Regular expressions

Rust does not provide built-in support for regular expressions, so we need to add the `regex` crate into `Cargo.toml`:

``````[dependencies]
regex = "1.5"``````

As an illustration, from https://turreta.com/2019/09/14/rust-validate-email-address-using-regular-expressions/ we’ll take a regular expression for basic email validation (if interested in this topic, please see the discussion in https://stackoverflow.com/questions/201323/how-to-validate-an-email-address-using-a-regular-expression ). In the following listing, a regular expression matcher is built with the `Regex::new()` method (the regular expression is compiled) and then is used to verify an email address provided by the user. Note that this program is a small evolution from the previous one:

``````use regex::Regex;
use std::io;
use std::io::Write;

pub struct SchoolScore {
period: String,
email: String,
score: i32,
}

// same as previous listing ...

fn input() -> SchoolScore {
let re = Regex::new(
r"^([a-z0-9_+]([a-z0-9_+.]*[a-z0-9_+])?)@([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6})",
)
.unwrap();
let period = input_string("Enter period> ");
let email;
loop {
let t_email = input_string("Enter email> ");
if re.is_match(&t_email) {
email = t_email;
break;
}
}
let score = input_number("Enter score> ");
SchoolScore {
period: period,
score: score,
email: email,
}
}``````
 Note For serious email address validation you should avoid regular expressions at all and employ a special purpose library like https://crates.io/crates/validator .
1. On invalid intput, the example just retry the input, but do not explain what’s happening: provide some information for the user in the error cases

2. Modify the regular expression in order to accept email addresses of an specific domain (like `university.edu`)

3. Remove the regular expressions support from `Cargo.toml` and add the `validator` crate for email address verification

### Random scores

The usual way of generating random numbers with with he help of the `rand::Rng` generator, which is obtained with the `rand::thread_rng()` function. In the following example we get values in the range `[0,21)`; that is, from zero to 20:

``````use rand::{thread_rng, Rng};

pub struct SchoolScore {
period: String,
score: i32,
}

fn main() {
let mut rndgen = thread_rng();
let s1 = SchoolScore {
period: String::from("January"),
score: rndgen.gen_range(0, 21),
};
let s2 = SchoolScore {
period: String::from("February"),
score: rndgen.gen_range(0, 21),
};
println!("AVG({},{}) ", s1.score, s2.score);
println!("PA={}", pa(&s1, &s2));
println!("PH={}", ph(&s1, &s2));
}

fn pa(a: &SchoolScore, b: &SchoolScore) -> i32 {
(a.score + b.score) / 2
}

fn ph(a: &SchoolScore, b: &SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}``````

This random number generator is not part of the Rust standard library, but an additional library: a Rust "crate". In order to make it available in the project, the create must be listed as a dependency in the `Cargo.toml` configuration file:

``````[dependencies]
rand = "0.5.5"``````

On the next project build, the library will be downloaded into the Rust installation for further use.

1. Search for the `rand` crate at https://crates.io/; what is its "current" version?

2. Read about the multiple ways to specify the dependency’s crate versions at https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html

3. See more ideas on random number generation in https://rust-lang-nursery.github.io/rust-cookbook/algorithms/randomness.html

4. From the previous link, investigate a more reasonable way to model random scores using the normal (https://docs.rs/rand_distr/0.4.0/rand_distr/struct.Normal.html) distribution, and improve the current simulation

### More on looping

With our random number generator, now we’ll create a disk file with any number of random scores. Observe the use of the `loop` keyword for the iteration and how it is terminated with an explicit `break`:

``````use rand::{thread_rng, Rng};
use std::fs::File;
use std::io;
use std::io::Write;

fn input_number(prompt: &str) -> u32 {
loop {
print!("{}", prompt);
io::stdout().flush().unwrap();
let mut line = String::new();
match io::stdin().read_line(&mut line) {
Ok(_) => (),
_ => continue,
}
match line.trim().parse() {
Ok(val) => return val,
_ => continue,
}
}
}

fn main() {
let num = input_number("How many records? ");
let mut rndgen = thread_rng();
let mut file = File::create("/tmp/test-output.txt").expect("Can't create file");
let mut z = 0;
loop {
if z >= num {
break;
}
let score = rndgen.gen_range(0, 21);
writeln!(&mut file, "{}->{}", z, score).unwrap();
z += 1;
}
}``````

In order to opening the file in "append" mode, change the `File::create()` call with something like:

``````let mut file = OpenOptions::new().append(true).
open("/tmp/test-output.txt").expect("Can't open file for append");``````
 Note There is no `close()` method for the file handle: the file is closed when its handler object goes out of score. The closing may be forced by destroying the handler by calling `drop(&file)`.

Execution test:

```diego@dataone:~/devel/RUST/xtut\$ cargo run --bin p0580
Compiling xtut v0.1.0 (/home/diego/devel/RUST/xtut)
Finished dev [unoptimized + debuginfo] target(s) in 0.73s
Running `target/debug/p0580`
How many records? 4
diego@dataone:~/devel/RUST/xtut\$ cat /tmp/test-output.txt
0->17
1->2
2->18
3->13```

Since this loop pattern is very common, Rust provides the classic `while condition {…​}` construct:

``````use rand::{thread_rng, Rng};
use std::fs::File;
use std::io;
use std::io::Write;

fn input_number(prompt: &str) -> u32 {
loop {
print!("{}", prompt);
io::stdout().flush().unwrap();
let mut line = String::new();
match io::stdin().read_line(&mut line) {
Ok(_) => (),
_ => continue,
}
match line.trim().parse() {
Ok(val) => return val,
_ => continue,
}
}
}

fn main() {
let num = input_number("How many records? ");
let mut rndgen = thread_rng();
let mut file = File::create("/tmp/test-output.txt").expect("Can't create file");
let mut z = 0;
while z < num {
let score = rndgen.gen_range(0, 21);
writeln!(&mut file, "{}->{}", z, score).unwrap();
z += 1;
}
}``````

and a `for range {…​}` construct, where the range is specified with the syntax `a..b` corresponding to the values `a`, `a+1`…​ `b-1`, but not including `b`. There is an alternative `a..=b` syntax for including the final extreme `b`.

``````use rand::{thread_rng, Rng};
use std::fs::File;
use std::io;
use std::io::Write;

fn input_number(prompt: &str) -> u32 {
loop {
print!("{}", prompt);
io::stdout().flush().unwrap();
let mut line = String::new();
match io::stdin().read_line(&mut line) {
Ok(_) => (),
_ => continue,
}
match line.trim().parse() {
Ok(val) => return val,
_ => continue,
}
}
}

fn main() {
let num = input_number("How many records? ");
let mut rndgen = thread_rng();
let mut file = File::create("/tmp/test-output.txt").expect("Can't create file");
for z in 0..num {
let score = rndgen.gen_range(0, 21);
writeln!(&mut file, "{}->{}", z, score).unwrap();
}
}``````
 Note The `for` range extremes are evaluated only once before the first loop iteration, and remain fixed until its termination, even if they were the result of some variable expression whose value would change during the loop.
1. Try to verify the last note regarding the `for` range immutablility: make the `num` a mutable variable, and inside the loop reset it to a small value (like zero)

2. Do the same test with the `while` loop example

### Modules

Modules introduce a controlled access scope and namespacing for types and functions. As a trivial example, the following listing does contain a module containing the averaging functions:

``````use rand::{thread_rng, Rng};

pub struct SchoolScore {
period: String,
score: i32,
}

fn main() {
let mut rndgen = thread_rng();
let s1 = SchoolScore {
period: String::from("January"),
score: rndgen.gen_range(0, 21),
};
let s2 = SchoolScore {
period: String::from("February"),
score: rndgen.gen_range(0, 21),
};
println!("AVG({},{}) ", s1.score, s2.score);
println!("PA={}", averaging::pa(&s1, &s2));
println!("PH={}", averaging::ph(&s1, &s2));
}

pub mod averaging {

pub fn pa(a: &super::SchoolScore, b: &super::SchoolScore) -> i32 {
(a.score + b.score) / 2
}

pub fn ph(a: &super::SchoolScore, b: &super::SchoolScore) -> i32 {
let af = a.score as f64;
let bf = b.score as f64;
let ans = 2.0 * af * bf / (af + bf);
ans.round() as i32
}
}``````

Here the `averaging` module is specified with the `mod name {…​}` syntax, but usualy, modules are stored in its own file with no need for this enclosing syntax; in this case, calling code needs to specify a `mod name;` declaration.

The `SchoolScore` type is outside the `averaging` module, which technically is the parent (default) module. For this reason, from the module it needs to be referenced whith the `super::SchoolScore` syntax.

To make things a bit confusing, module files may be created inside the `src/` directory with a file name `name.rs` which defines the module name, or inside a new subdirectory under `src/` with the predefined file name `mod.rs`; in this case, the subdirectory name defines the module name.

The code which is not under a module is added to a default module named `crate`.

1. Create a new project with the example code into `main.rs`, but put the `averaging` module in its own `averaging.rs` file (besides `main.rs`.)

2. In `averagin.rs`, make sure to remove the enclosing `mod averaging {…​}` since it is no longer needed (leaving it would define an `averaging::averaging` submodule)

3. Add the `mod averaging;` at the beginning of `main.rs` in order to access the module

4. The module functions are private by default. Remove the `pub` directive from the module functions to verify that the parent module is unable to access them

### Vectors

Let’s create a number of scores with the help of our random number generator:

``````use rand::distributions::Alphanumeric;
use std::io;
use std::io::Write;

#[derive(Debug)]
pub struct SchoolScore {
period: String,
score: i32,
}

fn input_number(prompt: &str) -> u32 {
loop {
print!("{}", prompt);
io::stdout().flush().unwrap();
let mut line = String::new();
match io::stdin().read_line(&mut line) {
Ok(_) => (),
_ => continue,
}
match line.trim().parse() {
Ok(val) => return val,
_ => continue,
}
}
}

fn build_record<R: Rng>(rng: &mut R) -> SchoolScore {
let sz = rng.gen_range(5, 16);
let period: String = rng.sample_iter(&Alphanumeric).take(sz).collect();
let score = rng.gen_range(0, 21);
SchoolScore { period, score }
}

fn main() {
let num = input_number("How many records? ");
let mut rndgen = thread_rng();
let mut records: Vec<SchoolScore> = Vec::new();
for _ in 0..num {
let rec = build_record(&mut rndgen);
records.push(rec);
}
for rec in records.iter() {
println!("Record is {:?}", rec);
}
}``````

The `Vec<T>` is a "vector" container similar to the corresponding C++ type or Java’s `ArrayList`: it allows the insertion of arbitrary number of same-type elements, preserving insertion order, and providing very fast access of the elements by position. We create a new vector with its `new()` static method, assigning to a mutable and explicitely typed variable (like `records` in the example.)

Since the `SchoolScore` type is composed from basic Rust types, a "debug view" may be automatically generated with the `#[derive(Debug)]` directive, so its instances may be printed with the `{:?}` placeholder notation.

Also, `Random::Rng` is a trait with for some unknown implementation, so we employ a trait bound in order to provide its value to the `build_record()` function. Note the use of the `sample_iter()` method used to generate random strings containing 5-15 characters; those characters are letters (upper and lower case) and numeric digits. Compare with the following implementation which generates random strings containing characters in the set `A-Z` (ASCII codes 65 to 90):

``````    // sample_iter() imitation
let mut period = String::new();
for _ in 0..rng.gen_range(5, 16) {
let ch = char::from(rng.gen_range(65, 91));
period.push(ch);
}``````

Returning to the vector, the `push()` method is used to append elements into it. An important functionality is shown in the display of the vector contents:

``````    for rec in records.iter() {
println!("Record is {:?}", rec);
}``````

Here the `for` keyword is running on a vector’s iterator obtained by `iter()`. This is a "read only" iterator which does not allow any kind of modification of the elements.

There are two other kinds of iterator obtained by:

``   for rec in records.iter_mut() {...}``

this iterator allows the modification of the elements while being iterated; and:

``    for rec in records.into_iter() {...}``

This iterator "consumes" the elements from the vector, and transfer the vector’s ownership into the function, so after the iteration, the vector variable can no longer be used. This last iteration mode may be abbreviated with the following syntax:

``    for rec in records {...} // like into_iter()``

For example, with the following modifications the last sample does not compile since the `records` variable was "moved" after the first loop:

``````    // ... previous lines same as before ...
for rec in records {
println!("1st run, record is {:?}", rec);
}
for rec in records {
println!("2nd run, record is {:?}", rec);
}``````

Of course, using `records.iter()` it would be okay.

1. Complete the `sample_iter()` imitation shown above in order to include lower case letters and digits

2. The vector contents are stored in memory. Set a limit for the size of the generation (for example, 100000 records)

3. Make the program to pause by requesting some text from the console before the final display of the records. Run the program, and while paused, check its memory consumption with the operating system utilities. Do it for several values of the the vector

### Averaging the vector

From the previous example, we’ll reinsert the calculation of the averaging functions, but now they will work for any number of values. Also, this version does show how to capture command line arguments: the number of elements must be specified in the command line. Following the C/Unix convention, the first argument (position zero) is the executable program name, and the second one (position 1) will be the user provided number.

The arguments are provided in a Rust specific type named `env::Args` which is an iterator. It is converted into a `Vec` for convenience.

``````use rand::distributions::Alphanumeric;
use std::env;

#[derive(Debug)]
pub struct SchoolScore {
period: String,
score: i32,
}

fn build_record<R: Rng>(rng: &mut R) -> SchoolScore {
let period: String = rng.sample_iter(&Alphanumeric).take(10).collect();
let score = rng.gen_range(0, 21);
SchoolScore { period, score }
}

fn main() {
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
panic!("Must provide the number of records");
}
let num = match args.parse() {
Ok(val) => val,
_ => panic!("Must provide the number of records"),
};
let mut rndgen = thread_rng();
let mut records: Vec<SchoolScore> = Vec::new();
for _ in 0..num {
let rec = build_record(&mut rndgen);
records.push(rec);
}
for rec in records.iter() {
println!("Record is {:?}", rec);
}
println!("PA={}", pa(&records));
println!("PH={}", ph(&records));
}

fn pa(data: &Vec<SchoolScore>) -> i32 {
let mut total: f64 = 0.0;
for rec in data.iter() {
total = total + f64::from(rec.score);
}
let n = data.len() as f64;
(total / n).round() as i32
}

fn ph(data: &Vec<SchoolScore>) -> i32 {
let mut total: f64 = 0.0;
for rec in data.iter() {
total = total + 1.0 / f64::from(rec.score);
}
let n = data.len() as f64;
(n / total).round() as i32
}``````

Besides iterators, vector elements may be extracted with the `var[position]` syntax (as in the `args` variable.) Usualy, it is better to take a reference with `&var[position]`, since the former transfer the ownership of the element from the vector. For example, the following program works as expected:

``````fn main() {
let mut something: Vec<String> = Vec::new();
something.push(String::from("one"));
something.push(String::from("two"));
something.push(String::from("three"));
let k = &something;
println!("element is {}", k);
}``````

But after changing the assignation of `k` into:

``let k = something;``

then we get the following error:

```error[E0507]: cannot move out of index of `Vec<String>`
--> src/bin/p0665.rs:6:13
|
6 |     let k = something;
|             ^^^^^^^^^^^^
|             |
|             move occurs because value has type `String`, which does not implement the `Copy` trait
|             help: consider borrowing here: `&something````

Another way to extract elements is with the `get(index)` method: it returns an `Option<&T>` where `None` is returned when the index is out of range.

1. If no command line arguments are provided, or if an invalid value is provided, then ask the user to provide the required value using the `input_number()` function shown in previous example

#### A vector application

This section is a recapilutation of the previous concepts. The following example shows a new `SchoolClass` containing a vector of `Strudent`s. The `SchoolClass` does not implements any trait, but has a number of methods: it behaves like a classic C++ or Java class.

The averaging functions now are methods which operate in the internal vector. The `best()` method is interesting in its return value: the `Option` may be `None` if no students were added to the `SchoolClass` instance.

``````#[derive(Debug)]
pub struct Student {
name: String,
age: u8,
sex: Sex,
score: u8,
}

#[derive(Debug)]
pub enum Sex {
MALE,
FEMALE,
}

pub struct SchoolClass {
name: String,
people: Vec<Student>,
}

impl SchoolClass {
fn new(name: &str) -> SchoolClass {
SchoolClass {
name: String::from(name),
people: Vec::new(),
}
}
fn new_student(&mut self, name: &str, age: u8, sex: Sex, score: u8) {
let s = Student {
name: String::from(name),
age: age,
sex: sex,
score: score,
};
self.people.push(s);
}
fn pa(&self) -> u8 {
let mut total: f64 = 0.0;
for rec in self.people.iter() {
total = total + f64::from(rec.score);
}
let n = self.people.len() as f64;
(total / n).round() as u8
}

fn ph(&self) -> u8 {
let mut total: f64 = 0.0;
for rec in self.people.iter() {
total = total + 1.0 / f64::from(rec.score);
}
let n = self.people.len() as f64;
(n / total).round() as u8
}

fn len(&self) -> usize {
self.people.len()
}

fn best(&self) -> Option<&Student> {
let mut idx: i32 = -1;
let mut cur_max: u8 = 0;
for (i, rec) in self.people.iter().enumerate() {
if rec.score > cur_max {
idx = i as i32;
cur_max = rec.score;
}
}
if idx < 0 {
return None;
}
Some(&self.people[idx as usize])
}
}

fn main() {
let mut school_class = SchoolClass::new("Rust 101");
school_class.new_student("Mike Schumacher", 21, Sex::MALE, 17);
school_class.new_student("Max Verstappen", 25, Sex::MALE, 19);
school_class.new_student("Checo Perez", 31, Sex::MALE, 18);
school_class.new_student("Marcus Mazepin", 22, Sex::MALE, 9);
println!("There are {} students", school_class.len());
println!("PA={}", school_class.pa());
println!("PH={}", school_class.ph());
let best_student = school_class.best();
println!("Best of class {}: {:?}", school_class.name, best_student);
}``````

See also the `enumerate()` method which is used for returning tuples containing the interation index (from zero) and the iterated element.

1. The averages will fail when there are no students in the vector; an `Option<u8>` would be a better return value for them

2. Implement a function to find the "worst" student

#### Initializing vectors

Rust provides the `vec!` macro to help in the initialization of vector values. The following example illustrates its usage by randomly combining names and last names. Observe the use of literal constants, so the resulting vector type is `Vec<&str>`:

``````use rand::{thread_rng, Rng};

#[derive(Debug)]
pub struct SchoolScore {
driver: String,
score: i32,
}

fn build_record<R: Rng>(rng: &mut R, fnames: &Vec<&str>, lnames: &Vec<&str>) -> SchoolScore {
let idx_fname = rng.gen_range(0, fnames.len());
let idx_lname = rng.gen_range(0, lnames.len());
let mut driver = String::new();
driver.push_str(fnames[idx_fname]);
driver.push_str(" ");
driver.push_str(lnames[idx_lname]);
let score = rng.gen_range(0, 21);
SchoolScore { driver, score }
}

fn main() {
let num = 5;
let fnames = vec![
"Mike",
"Niki",
"Ayrton",
"Max",
"Lewis",
"Kimi",
"Sebastian",
"Sergio",
"Jenson",
"Daniel",
];
let lnames = vec![
"Schumacher",
"Lauda",
"Senna",
"Verstappen",
"Hamilton",
"Raikkonen",
"Vettel",
"Perez",
"Button",
"Ricciardo",
"Russel",
];
let mut rndgen = thread_rng();
let mut records: Vec<SchoolScore> = Vec::new();
for _ in 0..num {
let rec = build_record(&mut rndgen, &fnames, &lnames);
records.push(rec);
}
for rec in records.iter() {
println!("Record is {:?}", rec);
}
}``````

A run example:

```diego@dataone:~/devel/RUST/xtut\$ cargo run --bin p0685
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
Running `target/debug/p0685`
Record is SchoolScore { driver: "Sergio Ricciardo", score: 16 }
Record is SchoolScore { driver: "Max Schumacher", score: 13 }
Record is SchoolScore { driver: "Mike Ricciardo", score: 11 }
Record is SchoolScore { driver: "Max Raikkonen", score: 0 }
Record is SchoolScore { driver: "Lewis Vettel", score: 19 }```

### Slices

The Slice types provide a "view" for a region of a vector, and other types containing collections of elements. If the contained elements are of type `T`, then the slice type is denoted by `[T]`.

It is not possible to transfer the ownership of "some contents" of a vector (or any related type), so the slices will normally be used as references: `&[T]`.

The slices may be obtained by methods in the `Slice` and `SliceMut` traits (like `as_slice()`), but usually they are automatically generated by "coercion". The previous example may be translated to slice notation simply by changing:

``fn build_record<R: Rng>(rng: &mut R, fnames: &Vec<&str>, lnames: &Vec<&str>) -> SchoolScore {...}``

into

``fn build_record<R: Rng>(rng: &mut R, fnames: &[&str], lnames: &[&str]) -> SchoolScore {...}``

The rest of the code remains exactly as before. That is, slices provide element access by the `var[position]` syntax, the `len()` method, etc.

The key is the automatic coercion by the syntax `&fnames` or `&lnames`: it generates a slice pointing to the full vector contents.

But there are more slice expressions; for example, changing the `build_record()` invocation to:

``let rec = build_record(&mut rndgen, &fnames[0..2], &lnames[0..3]);``

Does generate slices corresponding to views of only the first two and three elements of the mentioned vectors, respectively. A run of this program follows:

```diego@dataone:~/devel/RUST/xtut\$ cargo run --bin p0691
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
Running `target/debug/p0691`
Record is SchoolScore { driver: "Mike Schumacher", score: 17 }
Record is SchoolScore { driver: "Niki Schumacher", score: 11 }
Record is SchoolScore { driver: "Mike Schumacher", score: 12 }
Record is SchoolScore { driver: "Niki Senna", score: 14 }
Record is SchoolScore { driver: "Mike Schumacher", score: 9 }```

Note that `String` contained text may also be coerced to slice references. Its type is `&str`. See https://doc.rust-lang.org/stable/book/ch04-03-slices.html#string-slices for more information.

### Arrays

As in many programming languages, are compile time fixed-length ordered lists of same-type elements. For example, the following defines a five element array containing `&str` elements. This array’s type is denoted by `[&str;5]`:

``let some_array = ["ha", "he", "hi", "ho", "hu"];``

So the type `[T;n]` (where `n` is a non negative integer constant) denotes an array containing exactly `n` elements, each of type `T`.

The previous examples include two vectors which are never resized, so they may be replaced by arrays. And like vectors, arrays of type `[T;n]` (where `n` is ths array size) are coerced into slices of type `[T]`.

So, following with the previous examples, in order to interchange vectors by arrays the only required modification is to replace these lines:

``````let fnames = vec![
...
];
let lnames = vec![
...
]:``````

by the following:

``````let fnames = [
...
];
let lnames = [
...
]:``````

That all! Note that the types of both arrays are `[&str;10]` and `[&str;11]`; when calling by `&fname` or `&lname`, the arguments become coerced slice refences of type `&[&str]`. Now the full listing for the new version:

``````use rand::{thread_rng, Rng};

#[derive(Debug)]
pub struct SchoolScore {
driver: String,
score: i32,
}

fn build_record<R: Rng>(rng: &mut R, fnames: &[&str], lnames: &[&str]) -> SchoolScore {
let idx_fname = rng.gen_range(0, fnames.len());
let idx_lname = rng.gen_range(0, lnames.len());
let mut driver = String::new();
driver.push_str(fnames[idx_fname]);
driver.push_str(" ");
driver.push_str(lnames[idx_lname]);
let score = rng.gen_range(0, 21);
SchoolScore { driver, score }
}

fn pa(records: &[SchoolScore]) -> u8 {
let mut total: f64 = 0.0;
for rec in records.iter() {
total = total + f64::from(rec.score);
}
let n = records.len() as f64;
(total / n).round() as u8
}

fn ph(records: &[SchoolScore]) -> u8 {
let mut total: f64 = 0.0;
for rec in records.iter() {
total = total + 1.0 / f64::from(rec.score);
}
let n = records.len() as f64;
(n / total).round() as u8
}

fn main() {
let num = 5;
let fnames = [
"Mike",
"Niki",
"Ayrton",
"Max",
"Lewis",
"Kimi",
"Sebastian",
"Sergio",
"Jenson",
"Daniel",
];
let lnames = [
"Schumacher",
"Lauda",
"Senna",
"Verstappen",
"Hamilton",
"Raikkonen",
"Vettel",
"Perez",
"Button",
"Ricciardo",
"Russel",
];
let mut rndgen = thread_rng();
let mut records: Vec<SchoolScore> = Vec::new();
for _ in 0..num {
let rec = build_record(&mut rndgen, &fnames, &lnames);
records.push(rec);
}
for rec in records.iter() {
println!("Record is {:?}", rec);
}
println!("PA={}", pa(&records));
println!("PH={}", ph(&records));
}``````

### The `HashMap` container

Also known as dictionary or associative array, allows the unordered storage of single typed values, each one associated and referenced by a single type unique key value.

For example, the students in a school usualy have a unique code for clear identification. From our previous student class example, we’ll add a the `id` property for the students:

``````#[derive(Debug)]
pub struct Student {
id: String,
name: String,
age: u8,
sex: Sex,
score: u8,
}``````

The `id` is a `String` which (in this example) will contain an incrementing numeric value: this "counter" will be stored in the `SchoolClass` instance.

The `HashMap` is created by its `new()` static method and is parametric in two types: one for the keys and one for the values.

As shown in the next example, the iterator returns a pair containing the `(key,value)` pairs:

``````use std::collections::HashMap;

#[derive(Debug)]
pub struct Student {
id: String,
name: String,
age: u8,
sex: Sex,
score: u8,
}

#[derive(Debug)]
pub enum Sex {
MALE,
FEMALE,
}

pub struct SchoolClass {
name: String,
people: HashMap<String, Student>,
last_id: u64,
}

impl SchoolClass {
fn new(name: &str) -> SchoolClass {
SchoolClass {
name: String::from(name),
people: HashMap::new(),
last_id: 1000000,
}
}
fn new_student(&mut self, name: &str, age: u8, sex: Sex, score: u8) {
let id = self.last_id.to_string();
let idmap = id.clone();
self.last_id = self.last_id + 1;
let s = Student {
id: id,
name: String::from(name),
age: age,
sex: sex,
score: score,
};
self.people.insert(idmap, s);
}
fn pa(&self) -> u8 {
let mut total: f64 = 0.0;
for (_, rec) in self.people.iter() {
total = total + f64::from(rec.score);
}
let n = self.people.len() as f64;
(total / n).round() as u8
}

fn ph(&self) -> u8 {
let mut total: f64 = 0.0;
for (_, rec) in self.people.iter() {
total = total + 1.0 / f64::from(rec.score);
}
let n = self.people.len() as f64;
(n / total).round() as u8
}

fn len(&self) -> usize {
self.people.len()
}

fn best(&self) -> Option<&Student> {
let mut max_score: i32 = -1;
let mut the_best: Option<&Student> = Option::None;
for (_, rec) in self.people.iter() {
if rec.score as i32 > max_score {
max_score = rec.score as i32;
the_best = Some(rec);
}
}
the_best
}
}

fn main() {
let mut school_class = SchoolClass::new("Rust F1");
school_class.new_student("Mike Schumacher", 21, Sex::MALE, 17);
school_class.new_student("Max Verstappen", 25, Sex::MALE, 19);
school_class.new_student("Checo Perez", 31, Sex::MALE, 18);
school_class.new_student("Marcus Mazepin", 22, Sex::MALE, 9);
println!("There are {} students", school_class.len());
println!("PA={}", school_class.pa());
println!("PH={}", school_class.ph());
let best_student = school_class.best();
println!("Best of class {}: {:?}", school_class.name, best_student);
}``````

### Sorting values

Ordered containers like vectors provide sorting facilities. We want to produce a listing of the students of the previous example sorted by age.

Since `HashMap` is not an ordered container, as a first step will create a vector with references to the elements. Remember that the other options are:

1. A vector with clones from the elements (maybe too heavy)

2. Transfer the values from the `HashMap` (leaving it empty) into the vector

Note that this explicit distinction is one of the best selling points for Rust as compared to C/C++.

Our sorted vector will be generated from a `SchoolClass` method named `by_age()`:

``````impl SchoolClass {
// ... same as before ...
fn age_sorter(age1: &&Student, age2: &&Student) -> Ordering {
if age1.age > age2.age {
Ordering::Less
} else if age1.age < age2.age {
Ordering::Greater
} else {
Ordering::Equal
}
}

fn by_age(&self) -> Vec<&Student> {
let mut drivers: Vec<&Student> = Vec::new();
for (_, rec) in self.people.iter() {
drivers.push(rec);
}
drivers.sort_by(Self::age_sorter);
drivers
}
}

fn main() {
// ... same as before ...
let students_by_age = school_class.by_age();
for student in students_by_age.iter() {
println!("By age -> {:?}", student);
}
}``````

Here we use the `sort_by()` method which requires a comparator function, here named `age_sorter()`. The `sort_by()` calls the comparator with references to the vector elements. Since the elements have type `&Student`, then the calls will send values of type `&&Student`. This explains the `age_sorter()` signature.

#### Ordered types

There are many criteria for ordering a vector of complex data types as in the previous example. But some data types have a "natural" or "preferred" ordering which depends on the domain model. Let’s assume that the natural ordering for the students is based on their age. This situation in Rust is described by the implementation of the `Ord` trait.

As shown in https://doc.rust-lang.org/std/cmp/trait.Ord.html, this trait has the `Eq` and `PartialOrd` as super traits, so both traits must be implemented. They also have the `PartialEq` as super trait, so it also must be implemented.

When the `Ord` trait is implemented, then the `sort()` method is available as shown in the following listing. We removed the averaging methods for clarity:

``````use std::cmp::Ord;
use std::cmp::Ordering;
use std::collections::HashMap;

#[derive(Debug)]
pub struct Student {
id: String,
name: String,
age: u8,
sex: Sex,
score: u8,
}

#[derive(Debug)]
pub enum Sex {
MALE,
FEMALE,
}

pub struct SchoolClass {
name: String,
people: HashMap<String, Student>,
last_id: u64,
}

impl Ord for Student {
fn cmp(&self, other: &Self) -> Ordering {
self.age.cmp(&other.age)
}
}

impl Eq for Student {}

impl PartialOrd for Student {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl PartialEq for Student {
fn eq(&self, other: &Self) -> bool {
self.age == other.age
}
}

impl SchoolClass {
fn new(name: &str) -> SchoolClass {
SchoolClass {
name: String::from(name),
people: HashMap::new(),
last_id: 1000000,
}
}
fn new_student(&mut self, name: &str, age: u8, sex: Sex, score: u8) {
let id = self.last_id.to_string();
let idmap = id.clone();
self.last_id = self.last_id + 1;
let s = Student {
id: id,
name: String::from(name),
age: age,
sex: sex,
score: score,
};
self.people.insert(idmap, s);
}
fn by_age(&self) -> Vec<&Student> {
let mut drivers: Vec<&Student> = self.people.values().collect();
drivers.sort();
drivers
}
}

fn main() {
let mut school_class = SchoolClass::new("Rust F1");
school_class.new_student("Mike Schumacher", 21, Sex::MALE, 17);
school_class.new_student("Max Verstappen", 25, Sex::MALE, 19);
school_class.new_student("Checo Perez", 31, Sex::MALE, 18);
school_class.new_student("Marcus Mazepin", 22, Sex::MALE, 9);
let students_by_age = school_class.by_age();
for student in students_by_age.iter() {
println!("By age -> {:?}", student);
}
}``````

Note also that we created the vector by collecting the `HashMap` values, which in turm was obtained from the `values()` iterator.

### Introducing closures

The `sort_by()` method does require a comparator function, which previously was implemented as a usual method named `age_sorter`. This may be best served with an anonymous function, which provide the "closure" functionality of some programming languages. From https://doc.rust-lang.org/stable/book/ch13-01-closures.html:

"Rust’s closures are anonymous functions you can save in a variable or pass as arguments to other functions. You can create the closure in one place and then call the closure to evaluate it in a different context. Unlike functions, closures can capture values from the scope in which they’re defined."

The following version is an evolution from the `sort_by()` call. Here we replaced it by the `sort_unstable_by()` which may be a little faster:

``````use std::collections::HashMap;

#[derive(Debug)]
pub struct Student {
id: String,
name: String,
age: u8,
sex: Sex,
score: u8,
}

#[derive(Debug)]
pub enum Sex {
MALE,
FEMALE,
}

pub struct SchoolClass {
name: String,
people: HashMap<String, Student>,
last_id: u64,
}

impl SchoolClass {
fn new(name: &str) -> SchoolClass {
SchoolClass {
name: String::from(name),
people: HashMap::new(),
last_id: 1000000,
}
}
fn new_student(&mut self, name: &str, age: u8, sex: Sex, score: u8) {
let id = self.last_id.to_string();
let idmap = id.clone();
self.last_id = self.last_id + 1;
let s = Student {
id: id,
name: String::from(name),
age: age,
sex: sex,
score: score,
};
self.people.insert(idmap, s);
}
fn by_age(&self) -> Vec<&Student> {
let mut drivers: Vec<&Student> = self.people.values().collect();
drivers.sort_unstable_by(|a, b| a.age.cmp(&b.age));
drivers
}
}

fn main() {
let mut school_class = SchoolClass::new("Rust F1");
school_class.new_student("Mike Schumacher", 21, Sex::MALE, 17);
school_class.new_student("Max Verstappen", 25, Sex::MALE, 19);
school_class.new_student("Checo Perez", 31, Sex::MALE, 18);
school_class.new_student("Marcus Mazepin", 22, Sex::MALE, 9);
let students_by_age = school_class.by_age();
students_by_age
.iter()
.for_each(|s| println!("By age -> {:?}", s));
}``````

This example illustrates the annonymous function syntax notation: `|parameters…​| body`. Also, the final display was done with the help of the `for_each()` function, which executes a closure as many times as elements are provided by the iterator (as returned by the `iter()` method.)

We may further simplify the program by employing the `sort_by_key()` method, which requires a closure which provide `Ord`-implementing values to be used as sorting keys: for our students, their ages have type `u8` and this type already implements the `Ord` trait (see https://doc.rust-lang.org/std/primitive.u8.html#trait-implementations for more information):

``````    fn by_age(&self) -> Vec<&Student> {
let mut drivers: Vec<&Student> = self.people.values().collect();
drivers.sort_by_key(|st| st.age);
drivers
}``````

### Containing References

Imagine we have many `Student` objects, all of them included in the "total set", and some of them included in the "top set". We may model this situation with the containers:

``````let mut vec_total: Vec<Student>;
let mut vec_top: Vec<Student>;``````

For this solution to work, we will need to duplicate each student belonging to both sets, which may be a waste of memory. Also, when updating a student, we will need to modify one or two objects, with the corresponding complexity of this tracking.

In some cases, a better solution may be to store references to the students:

``````let mut vec_total: Vec<&Student>;
let mut vec_top: Vec<&Student>;``````

This will work as long the referenced objects are alive while the vectors are used. Let’s review an example:

``````#[derive(Debug)]
pub struct Student {
id: u32,
name: String,
age: u8,
score: u8,
}

impl Student {
fn new(id: u32, name: &str, age: u8, score: u8) -> Student {
Student {
id: id,
name: String::from(name),
age: age,
score: score,
}
}
}

fn pa(data: &Vec<&Student>) -> u8 {
let mut total: f64 = 0.0;
for st in data.iter() {
total = total + f64::from(st.score);
}
let n = data.len() as f64;
(total / n).round() as u8
}

fn ph(data: &Vec<&Student>) -> u8 {
let mut total: f64 = 0.0;
for st in data.iter() {
total = total + 1.0 / f64::from(st.score);
}
let n = data.len() as f64;
(n / total).round() as u8
}

/* fn ac(vec_total: &mut Vec<&Student>) {
let st = Student::new(1001, "Andres Calamaro", 50, 12);
vec_total.push(&st);
} */

fn main() {
let mut vec_total: Vec<&Student> = Vec::new();
let mut vec_top: Vec<&Student> = Vec::new();
let st = Student::new(1001, "Mike Schumacher", 21, 17);
vec_total.push(&st);
vec_top.push(&st);

let st = Student::new(1002, "Max Verstappen", 25, 19);
vec_total.push(&st);
vec_top.push(&st);

let st = Student::new(1003, "Checo Perez", 31, 18);
vec_total.push(&st);
vec_top.push(&st);

let st = Student::new(1004, "Marcus Mazepin", 22, 9);
vec_total.push(&st);

/* ac(&mut vec_total); */

println!("TOTAL PA={}", pa(&vec_total));
println!("TOTAL PH={}", ph(&vec_total));

println!("TOP   PA={}", pa(&vec_top));
println!("TOP   PH={}", ph(&vec_top));
}``````

The most important issue here is what happens when the commented lines are enabled:

```40 |     vec_total.push(&st);
|     ---------------^^^-
|     |              |
|     |              borrowed value does not live long enough```

The `st` object dies with the `ac()` function, so `&st` would be invalid, so Rust complains.

A third way to implement this scenary is the usage of "reference counting": here we will transfer the ownership of each object into one or many "intelligent references" to be stored in the vectors as needed. When all the containing references for an object are destroyed, then the object is destroyed:

``````use std::rc::Rc;

#[derive(Debug)]
pub struct Student {
id: u32,
name: String,
age: u8,
score: u8,
}

impl Student {
fn new(id: u32, name: &str, age: u8, score: u8) -> Student {
Student {
id: id,
name: String::from(name),
age: age,
score: score,
}
}
}

fn pa(data: &Vec<Rc<Student>>) -> u8 {
let mut total: f64 = 0.0;
for st in data.iter() {
total = total + f64::from(st.score);
}
let n = data.len() as f64;
(total / n).round() as u8
}

fn ph(data: &Vec<Rc<Student>>) -> u8 {
let mut total: f64 = 0.0;
for st in data.iter() {
total = total + 1.0 / f64::from(st.score);
}
let n = data.len() as f64;
(n / total).round() as u8
}

fn ac(vec_total: &mut Vec<Rc<Student>>) {
let st = Rc::new(Student::new(1001, "Andres Calamaro", 50, 12));
vec_total.push(st);
}

fn main() {
let mut vec_total: Vec<Rc<Student>> = Vec::new();
let mut vec_top: Vec<Rc<Student>> = Vec::new();
let st_total: Rc<Student> = Rc::new(Student::new(1001, "Mike Schumacher", 21, 17));
let st_top: Rc<Student> = Rc::clone(&st_total);
vec_total.push(st_total);
vec_top.push(st_top);

let st_total: Rc<Student> = Rc::new(Student::new(1002, "Max Verstappen", 25, 19));
let st_top: Rc<Student> = Rc::clone(&st_total);
vec_total.push(st_total);
vec_top.push(st_top);

let st_total: Rc<Student> = Rc::new(Student::new(1003, "Checo Perez", 31, 18));
let st_top: Rc<Student> = Rc::clone(&st_total);
vec_total.push(st_total);
vec_top.push(st_top);

let st_total: Rc<Student> = Rc::new(Student::new(1004, "Marcus Mazepin", 22, 9));
vec_total.push(st_total);

ac(&mut vec_total);

println!("TOTAL PA={}", pa(&vec_total));
println!("TOTAL PH={}", ph(&vec_total));

println!("TOP   PA={}", pa(&vec_top));
println!("TOP   PH={}", ph(&vec_top));
}``````

Now the `ac()` function works as expected, since it is transfered into the `Rc` object.

### Cells

A limitation with `Rc` references is that the underlying objects are immutable. Following our example, now we want to "improve" the scores lower than 14 using `Rc`. For this situation we want to "force" a mutable borrow from an immutable reference: this is accomplished by the `RefCell` type (and its partner `Cell`.) Our vector will store elements of type `Rc<RefCell<Student>>`:

``let mut vec_total: Vec<Rc<RefCell<Student>>>;``

In order to simplify the code, we’ll create an alias for this type:

``type V = Vec<Rc<RefCell<Student>>>;``

Our new program follows:

``````use std::cell::RefCell;
use std::rc::Rc;

#[derive(Debug)]
pub struct Student {
id: u32,
name: String,
age: u8,
score: u8,
}

impl Student {
fn new(id: u32, name: &str, age: u8, score: u8) -> Student {
Student {
id: id,
name: String::from(name),
age: age,
score: score,
}
}
}

type V = Vec<Rc<RefCell<Student>>>;

fn improve(data: &V) {
for st in data.iter() {
let mut refer = st.borrow_mut();
if refer.score < 14 {
refer.score = refer.score + 1;
}
}
}

fn pa(data: &V) -> u8 {
let mut total: f64 = 0.0;
for st in data.iter() {
total = total + f64::from(st.borrow().score);
}
let n = data.len() as f64;
(total / n).round() as u8
}

fn ph(data: &V) -> u8 {
let mut total: f64 = 0.0;
for st in data.iter() {
total = total + 1.0 / f64::from(st.borrow().score);
}
let n = data.len() as f64;
(n / total).round() as u8
}

fn ac(vec_total: &mut V) {
let st = Rc::new(RefCell::new(Student::new(1001, "Andres Calamaro", 50, 12)));
vec_total.push(st);
}

fn main() {
let mut vec_total: V = Vec::new();
let mut vec_top: V = Vec::new();
let st_total = Rc::new(RefCell::new(Student::new(1001, "Mike Schumacher", 21, 17)));
let st_top = Rc::clone(&st_total);
vec_total.push(st_total);
vec_top.push(st_top);

let st_total = Rc::new(RefCell::new(Student::new(1002, "Max Verstappen", 25, 19)));
let st_top = Rc::clone(&st_total);
vec_total.push(st_total);
vec_top.push(st_top);

let st_total = Rc::new(RefCell::new(Student::new(1003, "Checo Perez", 31, 18)));
let st_top = Rc::clone(&st_total);
vec_total.push(st_total);
vec_top.push(st_top);

let st_total = Rc::new(RefCell::new(Student::new(1004, "Marcus Mazepin", 22, 9)));
vec_total.push(st_total);

ac(&mut vec_total);
improve(&vec_total);

println!("TOTAL PA={}", pa(&vec_total));
println!("TOTAL PH={}", ph(&vec_total));

println!("TOP   PA={}", pa(&vec_top));
println!("TOP   PH={}", ph(&vec_top));
}``````

The key line is in the `improve()` function:

``let mut refer = st.borrow_mut();``

Here we are calling the `borrow_mut()` obtaining a mutable reference (of `RefMut` type.) It allows the modification of the underlying object as desired.

An direct generalization is to allow the cell to contain a trait object. The following partial listing shows the required changes in order to support the `type V = Vec<Rc<RefCell<dyn MayImprove>>>`:

``````use std::cell::RefCell;
use std::rc::Rc;

#[derive(Debug)]
pub struct Student {
id: u32,
name: String,
age: u8,
score: u8,
}

impl Student {
fn new(id: u32, name: &str, age: u8, score: u8) -> Student {
Student {
id: id,
name: String::from(name),
age: age,
score: score,
}
}
}

type V = Vec<Rc<RefCell<dyn MayImprove>>>;

trait MayImprove {
fn get_name(&self) -> &String;
fn get_score(&self) -> u8;
fn improve(&mut self);
}

impl MayImprove for Student {
fn get_name(&self) -> &String {
&self.name
}
fn get_score(&self) -> u8 {
self.score
}
fn improve(&mut self) {
if self.score < 14 {
self.score = self.score + 1;
}
}
}

fn improve(data: &V) {
for st in data.iter() {
let mut refer = st.borrow_mut();
refer.improve();
}
}``````

### Storing function pointers

A struct may "function pointers" as a way to implement dynamic dispatching. For example, the following program implements a "machine" in charge of the calculation of the class average, where the scores are dynamically added, and the averages are updated in turn:

``````struct AveragingMachine {
accumulated: f64,
counter: u16,
}

impl AveragingMachine {
fn add_score(&mut self, score: u8) {
self.counter = self.counter + 1;
self.accumulated = self.accumulated + score as f64;
}
fn average(&self) -> f64 {
self.accumulated / self.counter as f64
}
fn new() -> Self {
Self {
accumulated: 0.0,
counter: 0,
}
}
}

fn main() {
let mut machine = AveragingMachine::new();
println!("Current average: {}", machine.average());
println!("New average: {}", machine.average());
}``````

Let’s leverage and generalize this "machine" in order to process harmonic averages. Recalling the introduction of this text, the harmonic average may be defined as an arithmetic average of the inverse of the quantities, but with an additional inversion at the end:

``PH = 1 / [ (1/a + 1/b + ...)/n ] = 1 / PA{1/x}``

So, in order to calculate the harmonic average by leveraging the arithmetic average algorithm, we may consider the "pre-processing" of the elements to be accumulated; in terms of an anonymous function:

``|x| 1 / x``

Also, the answer needs a final "post-processing", which may be expressed with exactly the same previous anonymous function.

Note that the arithmetic average may be calculated as always by providing identity functions:

``````struct AveragingMachine {
accumulated: f64,
counter: u16,
pre_adder: fn(u8) -> f64,
post_answer: fn(f64) -> f64,
}

impl AveragingMachine {
fn add_score(&mut self, score: u8) {
self.counter = self.counter + 1;
self.accumulated = self.accumulated + (self.pre_adder)(score);
}
fn average(&self) -> f64 {
(self.post_answer)(self.accumulated / self.counter as f64)
}
fn new(pre_adder: fn(u8) -> f64, post_answer: fn(f64) -> f64) -> Self {
Self {
accumulated: 0.0,
counter: 0,
}
}
}

fn main() {
let mut machine = AveragingMachine::new(|x| x as f64, |x| x);
println!("Current average: {}", machine.average());
println!("New average: {}", machine.average());
}``````

Now, the harmonic average is calculated by modifying the anonymous functions:

``````// same as above

fn main() {
let mut machine_harmonic = AveragingMachine::new(|x| 1.0 / x as f64, |x| 1.0 / x);
println!("Current average: {}", machine_harmonic.average());
println!("New average: {}", machine_harmonic.average());
}``````

Finally, the quadratic average, more known as "root mean square" is defined by:

`RMS = SQRT[ (a^2 + b^2 + ...)/n ]`

Again, only the anonymous functions need to be updated:

``````// same as above

fn main() {
let mut machine_rms = AveragingMachine::new(|x| (x as f64) * (x as f64), |x| f64::sqrt(x));
println!("Current average: {}", machine_rms.average());
println!("New average: {}", machine_rms.average());
}``````

In the previous examples we avoided calling the anonymous functions as "closures", since they indeed do not "close" over any other variable. When a real closure is needed, then the traits `Fn`, `FnMut` and `FnOnce` are employed:

``````struct AveragingMachine<T, S>
where
T: Fn(u8) -> f64,
S: Fn(f64) -> f64,
{
accumulated: f64,
counter: u16,
}

impl<T, S> AveragingMachine<T, S>
where
T: Fn(u8) -> f64,
S: Fn(f64) -> f64,
{
fn add_score(&mut self, score: u8) {
self.counter = self.counter + 1;
self.accumulated = self.accumulated + (self.pre_adder)(score);
}
fn average(&self) -> f64 {
(self.post_answer)(self.accumulated / self.counter as f64)
}
fn new(pre_adder: T, post_answer: S) -> Self {
Self {
accumulated: 0.0,
counter: 0,
}
}
}

fn main() {
let n = 2;
let mut machine_pow =
AveragingMachine::new(|x| (x as f64).powf(n as f64), |x| x.powf(1.0 / n as f64));
println!("Current average: {}", machine_pow.average());
println!("New average: {}", machine_pow.average());
}``````

Everywhere you may find interesting information about the usefulness of threads. The Rust Programming Language provides details about the threading tradeoffs faced by the Rust creators: https://doc.rust-lang.org/book/ch16-01-threads.html and some basic examples may be find here: https://doc.rust-lang.org/rust-by-example/std_misc/threads.html .

Threads are started by providing a no-arguments closure to the `std::thread::spawn()` function. This method returns a "join handle" useful to await for the thread termination, and also (if needed) get a return value from it, corresponding to the passed closure return value.

Following our theme, we will try to calculate averages for students. Now we have several school classes, each with some number of students, and we want the total averages for the complete school. The averages will be calculated by combining the "weighted" averages for each class. The following program uses the random student data generator from previous examples, and calculates the total averages without employing threads:

``````use rand::{thread_rng, Rng};

#[derive(Debug)]
pub struct SchoolScore {
driver: String,
score: i32,
}

fn build_record<R: Rng>(rng: &mut R, fnames: &[&str], lnames: &[&str]) -> SchoolScore {
let idx_fname = rng.gen_range(0, fnames.len());
let idx_lname = rng.gen_range(0, lnames.len());
let mut driver = String::new();
driver.push_str(fnames[idx_fname]);
driver.push_str(" ");
driver.push_str(lnames[idx_lname]);
let score = rng.gen_range(1, 21);
SchoolScore { driver, score }
}

fn pa(records: &[SchoolScore]) -> u8 {
let mut total: f64 = 0.0;
for rec in records.iter() {
total = total + f64::from(rec.score);
}
let n = records.len() as f64;
(total / n).round() as u8
}

fn ph(records: &[SchoolScore]) -> u8 {
let mut total: f64 = 0.0;
for rec in records.iter() {
total = total + 1.0 / f64::from(rec.score);
}
let n = records.len() as f64;
(n / total).round() as u8
}

fn main() {
let fnames = [
"Mike",
"Niki",
"Ayrton",
"Max",
"Lewis",
"Kimi",
"Sebastian",
"Sergio",
"Jenson",
"Daniel",
];
let lnames = [
"Schumacher",
"Lauda",
"Senna",
"Verstappen",
"Hamilton",
"Raikkonen",
"Vettel",
"Perez",
"Button",
"Ricciardo",
"Russel",
];
let nclasses = 8;
let mut rndgen = thread_rng();
let mut records: Vec<Vec<SchoolScore>> = Vec::new();
for _ in 0..nclasses {
let nitems = rndgen.gen_range(5, 12);
let mut claz: Vec<SchoolScore> = Vec::new();
for _ in 0..nitems {
let rec = build_record(&mut rndgen, &fnames, &lnames);
claz.push(rec);
}
records.push(claz);
}
// find the averages
let mut results_vector: Vec<(usize, u8, u8)> = Vec::new();
for subvec in records.iter() {
let result = (subvec.len(), pa(subvec), ph(subvec));
results_vector.push(result);
}
let mut pa_sum: f64 = 0.0;
let mut ph_sum: f64 = 0.0;
let mut nsum: f64 = 0.0;
for (n, pa_val, ph_val) in results_vector {
let nf: f64 = f64::from(n as u32);
pa_sum = pa_sum + f64::from(pa_val) * nf;
ph_sum = ph_sum + nf / f64::from(ph_val);
nsum = nsum + nf;
}
println!("TOTAL PA={}, PH={}", pa_sum / nsum, nsum / ph_sum);
}``````

Now we want to make each class' average calculation in an independent thread, and later proceed to combine those averages in the main thread to get the final response. A first attempt may include the following code, note that the thread result will be captured in a vector containing the `thread::JoinHandle<T>` type:

``````    // find the averages
let mut join_vector: Vec<thread::JoinHandle<(usize, u8, u8)>> = Vec::new();
for subvec in records.iter() {
let jh = thread::spawn(|| (subvec.len(), pa(subvec), ph(subvec)));
join_vector.push(jh);
}``````

But this does not compile; here we show an extract from the compiler error messages:

```error[E0597]: `records` does not live long enough
--> src/bin/p0905.rs:79:19
|
79 |     for subvec in records.iter() {
|                   ^^^^^^^-------
|                   |
|                   borrowed value does not live long enough
|                   argument requires that `records` is borrowed for `'static`
...
94 | }
| - `records` dropped here while still borrowed```

The problem is the variable `records`, which is discarded when the main function terminates: the threads are using references to it (captured from `records.iter()`) and may try to employ them even after main does finalize. Rust alerts us that `records` "does not live long enough", and suggest a `'static` lifetime which here is not a good advice.

#### Moving the vector

Now we have a solution which does compile (we show only the final section):

``````use std::thread;
...
// find the averages
let mut join_vector = Vec::new();
for subvec in records {
let jh = thread::spawn(move || (subvec.len(), pa(&subvec), ph(&subvec)));
join_vector.push(jh);
}
let mut pa_sum: f64 = 0.0;
let mut ph_sum: f64 = 0.0;
let mut nsum: f64 = 0.0;
for child in join_vector {
let (n, pa_val, ph_val) = child.join().unwrap();
let nf: f64 = f64::from(n as u32);
pa_sum = pa_sum + f64::from(pa_val) * nf;
ph_sum = ph_sum + nf / f64::from(ph_val);
nsum = nsum + nf;
}
println!("TOTAL PA={}, PH={}", pa_sum / nsum, nsum / ph_sum);
}``````

Here we applied two concepts. First, the iteration did not employ `in records.iter()` but `in records.into_iter()` which in Rust may be abbreviated simply as `in records`. That means that the `records` vector is moved into the iteration, so nothing remains to be dropped at the end of `main()`:

``for subvec in records { ... }``

The second concept is new: the closure is now a "move" closure, obviously distinguished by the `move` keyword before the parameter list. In this case the referenced variables will forcibly be "moved" into the closure, so the "subvectors" will not be caually removed before the closure execution finishes. Note that `subvec` is a vector object (not a reference to it), so we provide `&subvec` for `pa()` and `ph()`:

``move || (subvec.len(), pa(&subvec), ph(&subvec))``

#### Reference counting

As shown above, the "move closures" capture the vector; sometimes this is undesirable (for example, the vector may be needed for further processing); since plain references don’t work because of unfulfilled lifetimes, reference counting may provide the solution. Before we’ve seen the `Rc` type which is indicated for single-threaded code; for multithreading reference counting Rust provides the `Arc` type. The following solution employs `Arc` references:

``````use std::sync::Arc;