文件操作
读取目录内容
当我们需要使用rust读取目录的中内容的时候,我们可以使用fs模块的read_dir方法,read_dir方法接收一个AsRef<Path>作为参数,返回值是一个Result<[ReadDir](#ahAt2)>类型的迭代器。
Option枚举
在Rust中我们经常使用的Option枚举类型为我们提供了许多有用的方法,其中比较学用的有is_some,is_none,get,expect和unwrap这几个。与此同时,Option还提供了其他很有用的方法。比如and_then和map方法等。
方法
and_then方法
方法签名:
pub fn and_then<U, F>(self, f: F) -> Option<U>whereF: FnOnce<T> -> Option<U>,
当Option的值是None时,and_then方法会直接返回None,否则就使用函数f来包装Some(i)中的i值并返回包装后的结果。示例如下:
fn sq(x: u32) -> Option<u32> { Some(x * x) }fn nope(_: u32) -> Option<u32> { None }assert_eq!(Some(2).and_then(sq).and_then(sq), Some(16));assert_eq!(Some(2).and_then(sq).and_then(nope), None);assert_eq!(Some(2).and_then(nope).and_then(sq), None);assert_eq!(None.and_then(sq).and_then(sq), None);
从示例和and_then方法的定义上我们可以看到,如果我们需要对一个Option中的内容进行转换,那么我们就可以使用and_then方法,同时不需要判断Option的值是一个Some还是一个None,因为and_then方法已经为我们做了这个判断。
map方法
方法签名:
pub fn map<U, F>(self, f: F) -> Option<U>whereF: FnOnce<T> -> U,
map方法可以把类型Option<T>转换为类型Option<U>,这个转换过程是通过接受的函数来完成的。示例如下:
let maybe_some_string = Some(String::from("Hello, World"));let maybe_some_len = maybe_some_string.map(|s| s.len());assert_eq!(maybe_some_len, Some(13));
迭代器
迭代器是Rust中一个很重要的概念,我们可以在Rust中通过迭代器实现函数式编程。Rust中的迭代器为我们提供了很多的迭代器方法,有了这些方法的帮助,我们就可以通过更加声明的方式来进行程序中数据的流转了。
归一方法:fold,reduce和try_fold方法。
reduce方法
reduce方法是最简单的一个归一方法,其方法签名如下:
fn reduce<F>(self, f: F) -> Option<Self::Item>whereF: FnMut(Self::Item, Self::Item) -> Self::Item,
reduce方法是把多个同类型的元素,通过调用一个归一函数来归一成一个同类型的元素。其最后的结果一定和之前的类型是一致的。具体的示例如下:
fn find_max<I>(iter: I) ->Option<I::Item>where I: Iterator,I::Item: Order{iter.reduce(|max, cur| if max > cur { max } else { cur } )}let a = [10, 20, 5, -23, 0];let b: [u32,0] = [];assert_eq!(find_max(a.iter()), Some(20));assert_eq!(find_max(b.iter()), None);
fold方法
fold也是一个归一迭代器方法。其签名如下:
fn fold<B, F>(self, init: B, f: F) -> BwhereF: FnMut(B, Self::Item) -> B
fold也是把多个相同类型的元素进行归一,最后得到单个元素。它和reduce的不同之处在于:reduce最终得到的元素和之前多个元素是同一个类型。但是fold就不一定了,fold最后归一的类型可以和之前的类型相同,也可以不同。我们从签名中就可以看出reduce和fold的区别。一来是最后的返回的类型可能不同。这一点,我们刚刚已经提到过了,还有一点是,我们可以为fold提供一个初始值,而reduce没有初始值的设置,fold的闭包的第一次调用的值是我们提供的初始值,而reduce第一次调用的值是其迭代器的第一个元素。
示例:
let a = [1, 2, 3];let sum = a.iter().fold(0,|acc, cur| acc + cur);assert_eq(sum, 6);
try_fold方法
try_fold也是一个归一迭代器的方法。
让我们先来看看try_fold的签名:
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> RwhereF: FnMut(B, Self::Item) -> RR: Try<Output = B>
通过和fold的方法的对比,我们发现try_fold和fold之间的不同之处在于最后的返回类型不同。try_fold相对fold而言,比fold的返回值多加了一层Try类型的包装。这个类型是和Option,Result以及ControllFlow是兼容的。现在添加两个例子加以说明:
示例1:
let a = [1, 2, 3];let sum = a.iter().try_fold(0i8, |acc, &curr| acc.checked_add(x));assert_eq!(sum, Some(6));
示例2: 短路操作
let a = [10, 20, 30, 100, 40, 50];let mut it = a.iter();let sum = it.try_fold(0i8, |acc, &cur| acc.checked_add(cur));assert_eq!(sum, None);assert_eq!(it.len(), 2);assert_eq!(it.next(), Some(&40));
通过示例2,我们可以发现try_fold是一个具有短路操作的迭代方法,其会在归一过程中遇到None的返回值的时候直接返回,不再迭代。这个特性可以让我们在迭代出现None的时候及时停止,减少不必要的迭代。
示例3: 和ControllFlow配合使用
use std::ops::ControllFlow;let triangular = (1..30).try_fold(0_i8, |prev, cur| {if let Some(next) = prev.checked_add(x) {ControllFlow::Continue(next)} else {ControllFlow::Break(prev)}})assert_eq!(triangular, ControllFlow::Break(120));
附录
枚举
Result
Result枚举是在Rustl中最常用的一个枚举类型之一。其有OK(T)和Err(E)两个成员。其中,OK(T)中包含了正常的内容,Err(E)中是出错的内容。除去有这两个类型之外,其还有is_ok()和is_err()两个方法,分别反映了结果是不是成功和失败。ok()方法会把Result<T,E>的结果转换为Option<T>的类型。err()方法会把Result<T,E>的结果转换为Option<E>的类型。
Result的方法有以下内容(包含部分):
| ok | err | is_ok | is_err | iter | map | map_err | map_or |
|---|---|---|---|---|---|---|---|
| map_or_else | flatten | expect | or | or_else | unwrap | unwrap_or | unwrap_or_defalut |
| unwrap_or_else | and | into_ok | into_ok_orr_err | into_err |
Option
Option枚举同样是在Rust中最常用的一个枚举类型之一。其中有Some(T)和None两个成员。其有is_some()和is_none()方法。
结构体
ReadDir结构体
ReadDir是一个结构体,这个结构体实现了Debug和Iterator这样的trait。其中,迭代器中的关联类型是一个Result<[DirEntry](#D35rH)>类型。迭代器的next()方法返回值一个Option<Result<DirEntry>>类型。
DirEntry结构体
DirEntry结构体有以下这些实现方法:path,metadata,file_type和file_name。
其中file_type中返回值是Result<FileType>类型。file_name返回的是一个OsString类型。
FileType结构体
FileType结构体有以下实现方法:is_dir,is_file和is_symlink。
OsString结构体
OsString结构体可以通过into_string()方法返回一个Result<String,OsString>类型的值。在没有发生错误的时候,OsString会返回String类型的值,如果在转换过程中发生的错误,那么就会把OsString原样返回。

