Читаем Rust by Example полностью

You can chain many ?s together to make your code much more readable.

struct Person {

job: Option,

}

#[derive(Clone, Copy)]

struct Job {

phone_number: Option,

}

#[derive(Clone, Copy)]

struct PhoneNumber {

area_code: Option,

number: u32,

}

impl Person {

// Gets the area code of the phone number of the person's job, if it exists.

fn work_phone_area_code(&self) -> Option {

// This would need many nested `match` statements without the `?` operator.

// It would take a lot more code - try writing it yourself and see which

// is easier.

self.job?.phone_number?.area_code

}

}

fn main() {

let p = Person {

job: Some(Job {

phone_number: Some(PhoneNumber {

area_code: Some(61),

number: 439222222,

}),

}),

};

assert_eq!(p.work_phone_area_code(), Some(61));

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

<p id="combinators_map"><strong><a l:href="#combinators_map">Combinators:</a><a l:href="#combinators_map">map</a></strong></p>

match is a valid method for handling Options. However, you may eventually find heavy usage tedious, especially with operations only valid with an input. In these cases, combinators can be used to manage control flow in a modular fashion.

Option has a built in method called map(), a combinator for the simple mapping of Some -> Some and None -> None. Multiple map() calls can be chained together for even more flexibility.

In the following example, process() replaces all functions previous to it while staying compact.

#![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);

// Peeling food. If there isn't any, then return `None`.

// Otherwise, return the peeled food.

fn peel(food: Option) -> Option {

match food {

Some(food) => Some(Peeled(food)),

None => None,

}

}

// Chopping food. If there isn't any, then return `None`.

// Otherwise, return the chopped food.

fn chop(peeled: Option) -> Option {

match peeled {

Some(Peeled(food)) => Some(Chopped(food)),

None => None,

}

}

// Cooking food. Here, we showcase `map()` instead of `match` for case handling.

fn cook(chopped: Option) -> Option {

chopped.map(|Chopped(food)| Cooked(food))

}

// A function to peel, chop, and cook food all in sequence.

// We chain multiple uses of `map()` to simplify the code.

fn process(food: Option) -> Option {

food.map(|f| Peeled(f))

.map(|Peeled(f)| Chopped(f))

.map(|Chopped(f)| Cooked(f))

}

Перейти на страницу:

Похожие книги