文件操作

读取目录内容

当我们需要使用rust读取目录的中内容的时候,我们可以使用fs模块的read_dir方法,read_dir方法接收一个AsRef<Path>作为参数,返回值是一个Result<[ReadDir](#ahAt2)>类型的迭代器。

Option枚举

Rust中我们经常使用的Option枚举类型为我们提供了许多有用的方法,其中比较学用的有is_some,is_none,get,expectunwrap这几个。与此同时,Option还提供了其他很有用的方法。比如and_thenmap方法等。

方法

and_then方法

方法签名:

  1. pub fn and_then<U, F>(self, f: F) -> Option<U>
  2. where
  3. F: FnOnce<T> -> Option<U>,

Option的值是None时,and_then方法会直接返回None,否则就使用函数f来包装Some(i)中的i值并返回包装后的结果。示例如下:

  1. fn sq(x: u32) -> Option<u32> { Some(x * x) }
  2. fn nope(_: u32) -> Option<u32> { None }
  3. assert_eq!(Some(2).and_then(sq).and_then(sq), Some(16));
  4. assert_eq!(Some(2).and_then(sq).and_then(nope), None);
  5. assert_eq!(Some(2).and_then(nope).and_then(sq), None);
  6. assert_eq!(None.and_then(sq).and_then(sq), None);

从示例和and_then方法的定义上我们可以看到,如果我们需要对一个Option中的内容进行转换,那么我们就可以使用and_then方法,同时不需要判断Option的值是一个Some还是一个None,因为and_then方法已经为我们做了这个判断。

map方法

方法签名:

  1. pub fn map<U, F>(self, f: F) -> Option<U>
  2. where
  3. F: FnOnce<T> -> U,

map方法可以把类型Option<T>转换为类型Option<U>,这个转换过程是通过接受的函数来完成的。示例如下:

  1. let maybe_some_string = Some(String::from("Hello, World"));
  2. let maybe_some_len = maybe_some_string.map(|s| s.len());
  3. assert_eq!(maybe_some_len, Some(13));

迭代器

迭代器是Rust中一个很重要的概念,我们可以在Rust中通过迭代器实现函数式编程。Rust中的迭代器为我们提供了很多的迭代器方法,有了这些方法的帮助,我们就可以通过更加声明的方式来进行程序中数据的流转了。
归一方法:fold,reducetry_fold方法。

reduce方法

reduce方法是最简单的一个归一方法,其方法签名如下:

  1. fn reduce<F>(self, f: F) -> Option<Self::Item>
  2. where
  3. F: FnMut(Self::Item, Self::Item) -> Self::Item,

reduce方法是把多个同类型的元素,通过调用一个归一函数来归一成一个同类型的元素。其最后的结果一定和之前的类型是一致的。具体的示例如下:

  1. fn find_max<I>(iter: I) ->Option<I::Item>
  2. where I: Iterator,
  3. I::Item: Order
  4. {
  5. iter.reduce(|max, cur| if max > cur { max } else { cur } )
  6. }
  7. let a = [10, 20, 5, -23, 0];
  8. let b: [u32,0] = [];
  9. assert_eq!(find_max(a.iter()), Some(20));
  10. assert_eq!(find_max(b.iter()), None);

fold方法

fold也是一个归一迭代器方法。其签名如下:

  1. fn fold<B, F>(self, init: B, f: F) -> B
  2. where
  3. F: FnMut(B, Self::Item) -> B

fold也是把多个相同类型的元素进行归一,最后得到单个元素。它和reduce的不同之处在于:reduce最终得到的元素和之前多个元素是同一个类型。但是fold就不一定了,fold最后归一的类型可以和之前的类型相同,也可以不同。我们从签名中就可以看出reducefold的区别。一来是最后的返回的类型可能不同。这一点,我们刚刚已经提到过了,还有一点是,我们可以为fold提供一个初始值,而reduce没有初始值的设置,fold的闭包的第一次调用的值是我们提供的初始值,而reduce第一次调用的值是其迭代器的第一个元素。
示例:

  1. let a = [1, 2, 3];
  2. let sum = a.iter().fold(0,|acc, cur| acc + cur);
  3. assert_eq(sum, 6);

try_fold方法

try_fold也是一个归一迭代器的方法。
让我们先来看看try_fold的签名:

  1. fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
  2. where
  3. F: FnMut(B, Self::Item) -> R
  4. R: Try<Output = B>

通过和fold的方法的对比,我们发现try_foldfold之间的不同之处在于最后的返回类型不同。try_fold相对fold而言,比fold的返回值多加了一层Try类型的包装。这个类型是和Option,Result以及ControllFlow是兼容的。现在添加两个例子加以说明:
示例1:

  1. let a = [1, 2, 3];
  2. let sum = a.iter().try_fold(0i8, |acc, &curr| acc.checked_add(x));
  3. assert_eq!(sum, Some(6));

示例2: 短路操作

  1. let a = [10, 20, 30, 100, 40, 50];
  2. let mut it = a.iter();
  3. let sum = it.try_fold(0i8, |acc, &cur| acc.checked_add(cur));
  4. assert_eq!(sum, None);
  5. assert_eq!(it.len(), 2);
  6. assert_eq!(it.next(), Some(&40));

通过示例2,我们可以发现try_fold是一个具有短路操作的迭代方法,其会在归一过程中遇到None的返回值的时候直接返回,不再迭代。这个特性可以让我们在迭代出现None的时候及时停止,减少不必要的迭代。
示例3: 和ControllFlow配合使用

  1. use std::ops::ControllFlow;
  2. let triangular = (1..30).try_fold(0_i8, |prev, cur| {
  3. if let Some(next) = prev.checked_add(x) {
  4. ControllFlow::Continue(next)
  5. } else {
  6. ControllFlow::Break(prev)
  7. }
  8. })
  9. 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是一个结构体,这个结构体实现了DebugIterator这样的trait。其中,迭代器中的关联类型是一个Result<[DirEntry](#D35rH)>类型。迭代器的next()方法返回值一个Option<Result<DirEntry>>类型。

DirEntry结构体

DirEntry结构体有以下这些实现方法:path,metadata,file_typefile_name
其中file_type中返回值是Result<FileType>类型。file_name返回的是一个OsString类型。

FileType结构体

FileType结构体有以下实现方法:is_dir,is_fileis_symlink

OsString结构体

OsString结构体可以通过into_string()方法返回一个Result<String,OsString>类型的值。在没有发生错误的时候,OsString会返回String类型的值,如果在转换过程中发生的错误,那么就会把OsString原样返回。

3ks