ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

rust实战系列 - 使用Iterator 迭代器实现斐波那契数列(Fibonacci )

2022-02-05 01:03:54  阅读:171  来源: 互联网

标签:Fib Iterator mut self 斐波 collect Fibonacci self.0 self.1


为什么是斐波那契数列

斐波那契数列十分适合用来实战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::<B> 帮助编译器推断类型

标签:Fib,Iterator,mut,self,斐波,collect,Fibonacci,self.0,self.1
来源: https://www.cnblogs.com/linyihai/p/15863717.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有