# rust real-world series - Fibonacci using Iterator iterator

Posted by co.ador on Fri, 04 Feb 2022 18:11:30 +0100

# Why Fibonacci Sequence

The Fibonacci sequence is well suited for the iterator used in real-world rust, and the algorithm is simple and straightforward. This example can be used to learn the use of Iterator and is a good example for practice after learning the iterator chapter of rust.

## Code Actual

don't bb, show me the code

```struct Fib(usize, usize);

impl Fib {
fn new() -> Fib {
Fib(0, 1)
}
}

impl Iterator for Fib {
type Item = usize;
fn next(&mut self) -> Option<usize> {
*self = Fib(self.1, self.0 + self.1);
Some(self.0)
}
}

fn main() {
let last = 20;
println!("fib({}) result: {:?}", last, Fib::new().take(last).collect::<Vec<usize>>());
}

```

## Decomposition Knowledge Points

1. The code defines a tuple structs named Fib. Since our implementation encapsulates implementation details, it is not necessary to define a named structure.
There are other structures on the web that give names, which I find redundant. Like this
```struct Fibonacci {
a: u64,
b: u64,
}
```
1. The second is how to implement Iterator. The key is to define the type of association and implement the next method
```impl Iterator for Fib {
// 1. Define the association type as usize
type Item = usize;
// 2. Implement the next method, which is also the main logic here
fn next(&mut self) -> Option<usize> {
*self = Fib(self.1, self.0 + self.1);
Some(self.0)
}
}
```
1. The third point is *self = Fib (self.1, self.0 + self.1). Self is defined as a variable reference (&mut), where *self dereferences are of type Fib.
Another way of writing
```self = &mut Fib(self.1, self.0 + self.1);
```

The above defines a mut Fib assignment to self, prompted directly by the rust compiler

```   |
12 |         self = &mut Fib(self.1, self.0 + self.1);
|         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot assign to immutable argument

error[E0716]: temporary value dropped while borrowed
--> src\main.rs:12:21
|
11 |     fn next(&mut self) -> Option<usize> {
|             - let's call the lifetime of this reference `'1`
12 |         self = &mut Fib(self.1, self.0 + self.1);
|         ------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
|         |           |
|         |           creates a temporary which is freed while still in use
|         assignment requires that borrow lasts for `'1`
```

The prompt borrows a temporary variable and the temporary variable is discarded. In fact, &mut Fib is just a variable borrowing and will expire immediately after being lent to self, which points to a dangling pointer, which the rust compiler will not allow (force a wave, welcome a face).
So the right thing to do is just let self take ownership of the newly created Fib. That is *self = Fib(self.1, self.0 + self.1);.

1. The fourth point is Fib:: new (). Take(last). Collect:: <Vec<usize>(). The results are printed directly here in the println macro, and the compiler cannot infer the type that needs to be collected. Instead, use the collect:: label.
The compiler can infer this automatically unless it is written in the following way
```let result: Vec<usize> = Fib::new().take(last).collect();
println!("fib({}) result: {:?}", last, result);

```

# summary

In order to implement Fibonacci series by rust iterator, we need to master some key points.

• Tuple Structural Writing
• How to implement iterator trait
• collect:: Helps the compiler infer types

# Why Fibonacci Sequence

The Fibonacci sequence is well suited for the iterator used in real-world rust, and the algorithm is simple and straightforward. This example can be used to learn the use of Iterator and is a good example for practice after learning the iterator chapter of rust.

## Code Actual

don't bb, show me the code

```struct Fib(usize, usize);

impl Fib {
fn new() -> Fib {
Fib(0, 1)
}
}

impl Iterator for Fib {
type Item = usize;
fn next(&mut self) -> Option<usize> {
*self = Fib(self.1, self.0 + self.1);
Some(self.0)
}
}

fn main() {
let last = 20;
println!("fib({}) result: {:?}", last, Fib::new().take(last).collect::<Vec<usize>>());
}

```

## Decomposition Knowledge Points

1. The code defines a tuple structs named Fib. Since our implementation encapsulates implementation details, it is not necessary to define a named structure.
There are other structures on the web that give names, which I find redundant. Like this
```struct Fibonacci {
a: u64,
b: u64,
}
```
1. The second is how to implement Iterator. The key is to define the type of association and implement the next method
```impl Iterator for Fib {
// 1. Define the association type as usize
type Item = usize;
// 2. Implement the next method, which is also the main logic here
fn next(&mut self) -> Option<usize> {
*self = Fib(self.1, self.0 + self.1);
Some(self.0)
}
}
```
1. The third point is *self = Fib (self.1, self.0 + self.1). Self is defined as a variable reference (&mut), where *self dereferences are of type Fib.
Another way of writing
```self = &mut Fib(self.1, self.0 + self.1);
```

The above defines a mut Fib assignment to self, prompted directly by the rust compiler

```   |
12 |         self = &mut Fib(self.1, self.0 + self.1);
|         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot assign to immutable argument

error[E0716]: temporary value dropped while borrowed
--> src\main.rs:12:21
|
11 |     fn next(&mut self) -> Option<usize> {
|             - let's call the lifetime of this reference `'1`
12 |         self = &mut Fib(self.1, self.0 + self.1);
|         ------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
|         |           |
|         |           creates a temporary which is freed while still in use
|         assignment requires that borrow lasts for `'1`
```

The prompt borrows a temporary variable and the temporary variable is discarded. In fact, &mut Fib is just a variable borrowing and will expire immediately after being lent to self, which points to a dangling pointer, which the rust compiler will not allow (force a wave, welcome a face).
So the right thing to do is just let self take ownership of the newly created Fib. That is *self = Fib(self.1, self.0 + self.1);.

1. The fourth point is Fib:: new (). Take(last). Collect:: <Vec<usize>(). The results are printed directly here in the println macro, and the compiler cannot infer the type that needs to be collected. Instead, use the collect:: label.
The compiler can infer this automatically unless it is written in the following way
```let result: Vec<usize> = Fib::new().take(last).collect();
println!("fib({}) result: {:?}", last, result);

```

# summary

In order to implement Fibonacci series by rust iterator, we need to master some key points.

• Tuple Structural Writing
• How to implement iterator trait
• Collect:: <B>Helps the compiler infer types

Topics: Back-end Rust