#![allow(dead_code)]
#[derive(Debug)] enum Food { Apple, Carrot, Potato }
#[derive(Debug)] struct Peeled(Food);
#[derive(Debug)] struct Chopped(Food);
#[derive(Debug)] struct Cooked(Food);
// 음식의 껍질. 없으면 `None`을 반환.
// 그렇지 않으면 껍질을 벗긴 음식을 반환.
fn peel(food: Option<Food>) -> Option<Peeled> {
match food {
Some(food) => Some(Peeled(food)),
None => None,
}
}
// 음식 자르기. 아무 것도 없으면 `None`을 반환.
// 그렇지 않으면 다진 음식을 반환.
fn chop(peeled: Option<Peeled>) -> Option<Chopped> {
match peeled {
Some(Peeled(food)) => Some(Chopped(food)),
None => None,
}
}
// 음식 요리하기. 여기서는 보여주기 용으로 `map()`을 `match`대신 사용해 처리한다.
fn cook(chopped: Option<Chopped>) -> Option<Cooked> {
chopped.map(|Chopped(food)| Cooked(food))
}
// 음식 껍질을 벗기고 자르고 조리를 순서대로 하는 함수.
// `map()`을 연결해서 연속으로 사용하여 코드를 단순화 했다.
fn process(food: Option<Food>) -> Option<Cooked> {
food.map(|f| Peeled(f))
.map(|Peeled(f)| Chopped(f))
.map(|Chopped(f)| Cooked(f))
}
// 그것을 먹기 전에 음식이 있는지 여부를 확인하라!
fn eat(food: Option<Cooked>) {
match food {
Some(food) => println!("Mmm. I love {:?}", food),
None => println!("Oh no! It wasn't edible."),
}
}
fn main() {
let apple = Some(Food::Apple);
let carrot = Some(Food::Carrot);
let potato = None;
let cooked_apple = cook(chop(peel(apple)));
let cooked_carrot = cook(chop(peel(carrot)));
// 이제 더 간단해 보이는 `process()`를 호출해보자.
let cooked_potato = process(potato);
eat(cooked_apple);
eat(cooked_carrot);
eat(cooked_potato);
}