为什么是斐波那契数列

斐波那契数列十分适合用来实战rust的迭代器,算法也很简单,一目了然。这个例子可以用来学习Iterator的使用,十分适合刚学习了rust的迭代器章节后用来练练手。

代码实战

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>>());
}

分解知识点

  1. 代码定义了一个名字为Fib的元组结构体(tuple structs)。因为我们的实现封装了实现细节,没必要定义一个具名结构体。

    网上有给出其他定义了名称的结构体,个人觉得有点多余了。比如这样
struct Fibonacci {
a: u64,
b: u64,
}
  1. 第二点就是如何实现Iterator,关键就两点,定义关联类型和实现next方法
impl Iterator for Fib {
// 1. 定义关联类型为usize
type Item = usize;
// 2. 实现next方法,这里也是主要的逻辑
fn next(&mut self) -> Option<usize> {
*self = Fib(self.1, self.0 + self.1);
Some(self.0)
}
}
  1. 第三点是*self = Fib(self.1, self.0 + self.1);; self被定义为了可变引用(&mut), 这里*self 解引用为Fib类型。

    另外一种写法
self = &mut Fib(self.1, self.0 + self.1);

上面定义了一个可变引用 &mut Fib 赋值给self,rust编译器直接提示

   |
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`

提示借用了临时变量,临时变量会被丢弃掉。其实就是&mut Fib 只是一个可变借用,在被借用给self后就会马上失效了,self就会指向一个悬垂指针, rust编译器肯定不会让这种情况发生的(强行解释一波,欢迎打脸)。

所以正确的做法是直接让self获取新创建的Fib的所有权就行了。也就是*self = Fib(self.1, self.0 + self.1);

  1. 第四点是Fib::new().take(last).collect::<Vec<usize>>()。 这里直接在println宏里打印结果,编译器推断不出需要collect的类型,需要使用collect::标注。

    除非是下面这种写法,编译器能自动推断出来

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

总结

本文通过rust iterator来实现斐波那契数列,需要掌握一下要点

  • 元组结构体写法
  • 如何实现iterator trait
  • collect:: 帮助编译器推断类型


rust实战系列 - 使用Iterator 迭代器实现斐波那契数列(Fibonacci )的更多相关文章

  1. python实现斐波那契数列(Fibonacci sequence)

    使用Python实现斐波那契数列(Fibonacci sequence) 斐波那契数列形如 1,1,2,3,5,8,13,等等.也就是说,下一个值是序列中前两个值之和.写一个函数,给定N,返回第N个斐 ...

  2. 斐波那契数列(Fibonacci) iOS

    斐波那契数列Fibonacci 斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2 ...

  3. 使用一位数组解决 1 1 2 3 5 8 13 数列问题 斐波纳契数列 Fibonacci

    斐波纳契数列 Fibonacci 输出这个数列的前20个数是什么? 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 使用数组实现输出数列的前30 ...

  4. 使用并行的方法计算斐波那契数列 (Fibonacci)

    更新:我的同事Terry告诉我有一种矩阵运算的方式计算斐波那契数列,更适于并行.他还提供了利用TBB的parallel_reduce模板计算斐波那契数列的代码(在TBB示例代码的基础上修改得来,比原始 ...

  5. Go斐波拉契数列(Fibonacci)(多种写法)

    1 前言 斐波拉契数列有递归写法和尾递归和迭代写法. 2 代码 //recursion func fib(n int) int{ if n < 2{ return n }else{ return ...

  6. poj3070_斐波那契数列(Fibonacci)

    用矩阵求斐波那契数列,快速幂log(n),只用求最后4位(加和乘的运算中前面的位数无用) #include <stdio.h> #include <stdlib.h> int ...

  7. 练习六:斐波那契数列(fibonacci)

    题目:斐波那契数列. 程序分析:斐波那契数列(Fibonacci sequence),又称黄金分割数列,指的是这样一个数列:0.1.1.2.3.5.8.13.21.34.……. 在数学上,斐波那契数列 ...

  8. Java实现斐波那契数列Fibonacci

    import java.util.Scanner; public class Fibonacci { public static void main(String[] args) { // TODO ...

  9. k阶斐波那契数列fibonacci第n项求值

    已知K阶斐波那契数列定义为:f0 = 0,  f1 = 0, … , fk-2 = 0, fk-1 = 1;fn = fn-1 + fn-2 + … + fn-k , n = k , k + 1, … ...

随机推荐

  1. 【LeetCode】592. Fraction Addition and Subtraction 解题报告(Python)

    [LeetCode]592. Fraction Addition and Subtraction 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuem ...

  2. API 网关功能

    反向代理和路由 - 大多数项目采用网关的解决方案的最主要的原因.给出了访问后端 API 的所有客户端的单一入口,并隐藏内部服务部署的细节. 负载均衡 - 网关可以将单个传入的请求路由到多个后端目的地. ...

  3. vue 滚动公告

    <!-- 滚动公告 --> <div class="textArr"> <p class="slice-enter-active" ...

  4. 编写Java程序,演练静态内部类应用

    返回本章节 返回作业目录 需求说明: 创建一个Person类,在该类中定义一个Home静态内部类,并在这个Home类中定义一个显示Home相关信息的方法. 在Person类中设置一个Home类型属性对 ...

  5. Ranger-AdminServer安装Version2.0.0

    Ranger-AdminServer安装, 对应的Ranger版本2.0.0. 1.安装规划 RangerAdmin安装依赖如下组件: mysql solr IP/机器名 安装软件 运行进程 dap2 ...

  6. Springboot+Javamail实现邮件发送

    Springboot+Javamail实现邮件发送 使用的是spring-context-support-5.2.6.RELEASE.jar里的javamail javamail 官方文档:javam ...

  7. Oracle:使用PL-SQL登录时报ORA-12541:无监听程序的解决办法

    背景: 在自己公司安装的Oracle,当时Oracle的监听地址都是写的公司的地址 后来由于项目需要,办公地点转移到了客户处, 大概有半年没有以sys用户登录数据库了. 最近在上下班途中学习Djang ...

  8. linux 三剑客(持续更新)排版后续再说,边学边记笔记

    切记:seq命令用于产生从某个数到另外一个数之间的所有整数.sed才是处理文本的命令 在遇到扩展符号时,需要添加特定参数,| () +[] 为扩展符号时,必须添加参数 egrep/grep -E  s ...

  9. Golang实现集合(set)

    package set package set import ( "bytes" "fmt" "sync" ) type Set struc ...

  10. Echart可视化学习(五)

    文档的源代码地址,需要的下载就可以了(访问密码:7567) https://url56.ctfile.com/f/34653256-527823386-04154f 常见的数据可视化库: D3.js ...