Rust 返回选项时不需要某些选项?

Rust 返回选项时不需要某些选项?,rust,Rust,我正在做“示例生锈”部分,并决定自己动手,看看使用map而不是和_then需要付出多大的努力 在我的尝试中,我遇到了一些非常奇怪的事情(在我看来,这甚至像是一个编译器错误)。当返回类型应该是选项(食物) 在我看来,下面的cookable功能应该可以简化为一行: have_ingredients(food).map(|f| can_cook(f)) 显然,它也可以是以下内容: have_ingredients(food).and_then(can_cook) 虽然我看不出这两个函数之间的根本区

我正在做“示例生锈”部分,并决定自己动手,看看使用
map
而不是
和_then
需要付出多大的努力

在我的尝试中,我遇到了一些非常奇怪的事情(在我看来,这甚至像是一个编译器错误)。当返回类型应该是
选项(食物)

在我看来,下面的
cookable
功能应该可以简化为一行:

have_ingredients(food).map(|f| can_cook(f))
显然,它也可以是以下内容:

have_ingredients(food).and_then(can_cook)
虽然我看不出这两个函数之间的根本区别,因为它们都返回一个
选项

在执行此操作时,我遇到了一个奇怪的编译器错误,因此我显式地将匹配项分解如下——看起来编译器希望返回
Food
,即使返回类型是
Some(Food)
。发生了什么事

//! stack.rs
#[derive(Debug)]
enum Food {
    CordonBleu,
    Steak,
    Sushi,
}

#[derive(Debug)]
enum Day {
    Monday,
    Tuesday,
    Wednesday,
}

/// we don't have the ingredients for sushi
fn have_ingredients(food: Food) -> Option<Food> {
    match food {
        Food::Sushi => None,
        _ => Some(food),
    }
}

/// can cook anything but cordon blue
fn can_cook(food: Food) -> Option<Food> {
    match food {
        Food::CordonBlue => None,
        _ => Some(food),
    }
}

/// can be done using map
fn cookable(food: Food) -> Option<Food> {
    match have_ingredients(food).map(|f| can_cook(f)) {
        // Some(food) => food,  // Why is this correct???
        Some(food) => Some(food), // **error: mismatched types:
        None => None,
    }
}

fn eat(food: Food, day: Day) {
    match cookable(food) {
        Some(food) => println!("Yay! On {:?} we eat {:?}", day, food),
        None => println!("Oh no we didn't get to eat on {:?}!", day),
    };
}

fn main() {
    let (cordon_bleu, steak, sushi) = (Food::CordonBleu, Food::Steak, Food::Sushi);
    eat(cordon_bleu, Day::Monday);
    eat(steak, Day::Tuesday);
    eat(sushi, Day::Wednesday);
}
/!stack.rs
#[导出(调试)]
列举食物{
科登布鲁,
牛排,
寿司
}
#[导出(调试)]
枚举日{
星期一,
星期二,
星期三,
}
///我们没有寿司的配料
fn有_成分(食物:食物)->选项{
配餐{
食物:寿司=>无,
_=>一些(食物),
}
}
///除了考顿蓝,我什么都会做
fn可以做饭(食物:食物)->选择{
配餐{
食物::CordonBlue=>无,
_=>一些(食物),
}
}
///可以使用map来完成
fn可烹饪(食物:食物)->选项{
火柴有配料(食物)。地图(| f | can|u cook(f)){
//一些(食物)=>食物,//为什么这是正确的???
部分(食物)=>部分(食物),//**错误:类型不匹配:
无=>无,
}
}
fn吃(食物:食物,天:天){
火柴(食物){
一些(食物)=>println!(“耶!在{:?}我们吃{:?}”,白天,食物),
None=>println!(“哦,不,我们没有在{:?}!”那天吃饭),
};
}
fn main(){
let(cordon_bleu,牛排,寿司)=(食物::CordonBleu,食物::牛排,食物::寿司);
吃(蓝色警戒线,星期一);
吃(牛排,星期二);
吃(寿司,星期三);
}
以下是上述程序的完整编译器错误:

 ch16_errors git:(master) ✗ rustc stack.rs
stack.rs:38:28: 38:32 error: mismatched types:
 expected `Food`,
    found `core::option::Option<Food>`
(expected enum `Food`,
    found enum `core::option::Option`) [E0308]
stack.rs:38         Some(food) => Some(food),
                                       ^~~~
stack.rs:38:28: 38:32 help: run `rustc --explain E0308` to see a detailed explanation
error: aborting due to previous error
ch16\u错误git:(主)✗ rustc stack.rs
stack.rs:38:28:38:32错误:不匹配的类型:
预期的“食物”,
找到'core::option::option'`
(应为枚举'Food',
找到枚举'core::option::option`)[E0308]
堆栈:38一些(食物)=>一些(食物),
^~~~
stack.rs:38:28:38:32帮助:运行'rustc--explain E0308'查看详细说明
错误:由于上一个错误而中止
提供一个
选项
,而不是
选项
,因为
映射
不会展平值

考虑

Option<T>::map(Fn(T) -> U)
它提供了一个
选项

因此,匹配中的
某些(食物)
具有
类型的
选项


然后_
将结果类型展平,这就是为什么它不会出现这种情况。

我现在明白了。首先,编译器错误表示它希望第一个食物是类型食物。其次,map的目的是让您编写一个简短的闭包,而不需要在其中编写一些(t)。
Option<T>::map(Fn(T) -> U)
Option<Food>::map(Fn(Food) -> Option<Food>)