• 组合算子:and_then
    • 参见:

    组合算子:and_then

    map() 以链式调用的方式来简化 match 语句。然而,在返回类型是 Option<T> 的函数中使用 map() 会导致出现嵌套形式 Option<Option<T>>。多层链式调用也会变得混乱。所以有必要引入 and_them(),就像某些熟知语言中的 flatmap。

    and_then() 使用包裹的值(wrapped value)调用其函数输入并返回结果。 如果 OptionNone,那么它返回 None

    在下面例子中,cookable_v2() 会产生一个 Option<Food>。使用 map() 替代 and_then() 将会得到 Option<Option<Food>>,对 eat() 来说是一个无效类型。

    1. #![allow(dead_code)]
    2. #[derive(Debug)] enum Food { CordonBleu, Steak, Sushi }
    3. #[derive(Debug)] enum Day { Monday, Tuesday, Wednesday }
    4. // 我们没有原材料(ingredient)来制作寿司。
    5. fn have_ingredients(food: Food) -> Option<Food> {
    6. match food {
    7. Food::Sushi => None,
    8. _ => Some(food),
    9. }
    10. }
    11. // 我们拥有全部食物的食谱,除了欠缺高超的烹饪手艺。
    12. fn have_recipe(food: Food) -> Option<Food> {
    13. match food {
    14. Food::CordonBleu => None,
    15. _ => Some(food),
    16. }
    17. }
    18. // 做一份好菜,我们需要原材料和食谱这两者。
    19. // 我们可以借助一系列 `match` 来表达相应的逻辑:
    20. // (原文:We can represent the logic with a chain of `match`es:)
    21. fn cookable_v1(food: Food) -> Option<Food> {
    22. match have_ingredients(food) {
    23. None => None,
    24. Some(food) => match have_recipe(food) {
    25. None => None,
    26. Some(food) => Some(food),
    27. },
    28. }
    29. }
    30. // 这可以使用 `and_then()` 方便重写出更紧凑的代码:
    31. fn cookable_v2(food: Food) -> Option<Food> {
    32. have_ingredients(food).and_then(have_recipe)
    33. }
    34. fn eat(food: Food, day: Day) {
    35. match cookable_v2(food) {
    36. Some(food) => println!("Yay! On {:?} we get to eat {:?}.", day, food),
    37. None => println!("Oh no. We don't get to eat on {:?}?", day),
    38. }
    39. }
    40. fn main() {
    41. let (cordon_bleu, steak, sushi) = (Food::CordonBleu, Food::Steak, Food::Sushi);
    42. eat(cordon_bleu, Day::Monday);
    43. eat(steak, Day::Tuesday);
    44. eat(sushi, Day::Wednesday);
    45. }

    参见:

    闭包,Option::map(), 和 Option::and_then()