Почему мы используем перечисление Option? - PullRequest
0 голосов
/ 08 июня 2019

Я не понимаю, для чего предназначен перечисление Option.Я читал, что Rust не имеет нулевых значений.Перечисление Option определено так:

enum Option<T> {
    Some(T),
    None,
}

Я прочитал его реализацию и натолкнулся на этот пример:

fn main() {
    fn divide(numerator: f64, denominator: f64) -> Option<f64> {
        if denominator == 0.0 {
            None
        } else {
            Some(numerator / denominator)
        }
    }

    // The return value of the function is an option
    let result = divide(2.0, 3.0);

    // Pattern match to retrieve the value
    match result {
        // The division was valid
        Some(x) => println!("Result: {}", x),
        // The division was invalid
        None => println!("Cannot divide by 0"),
    }
}

Когда они также могли сделать это так:

fn main() {
    fn divide(numerator: f64, denominator: f64) -> String {
        if denominator == 0.0 {
            format!("Can't divide")
        } else {
            let x = numerator / denominator;
            format!("{}", x)
        }
    }

    let result = divide(2.0, 3.0);
    println!("{}", result);
}

Вывод обеих программ:

0.6666666666666666

1 Ответ

1 голос
/ 08 июня 2019

Возможно, приведенный выше пример не очень хороший пример Option, но следующий пример показывает Option в самом лучшем виде:

fn main() {
    let name = String::from("naufil");
    println!(
        "Character at index 6: {}",
        match name.chars().nth(6) {
            Some(c) => c.to_string(),
            None => "No character at index 6!".to_string(),
        }
    )
}

Когда мы не уверены, существует ли символна 6-м элементе, и вы не хотите, чтобы ваша программа вылетала, Option приходит на помощь.Вот еще один пример из Rust Programming Language :

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);

Листинг 6-5: Функция, которая использует выражение match дляOption<i32>

Давайте рассмотрим первое выполнение plus_one более подробно.Когда мы вызываем plus_one(five), переменная x в теле plus_one будет иметь значение Some(5).Затем мы сравниваем это с каждым плечом матча.

None => None,

Значение Some(5) не соответствует шаблону None, поэтому мы переходим к следующему плечу.

Some(i) => Some(i + 1),

Some(5) соответствует Some(i)?Почему да, это так!У нас такой же вариант.i привязывается к значению, содержащемуся в Some, поэтому i принимает значение 5.Затем выполняется код в ответвлении, поэтому мы добавляем 1 к значению i и создаем новое значение Some с нашим общим 6 внутри.

Теперь давайте рассмотрим второй вызовplus_one в листинге 6-5, где x равно None.Вводим match и сравниваем с первым рычагом.

None => None,

Соответствует!Нет значения для добавления, поэтому программа останавливается и возвращает значение None справа от =>.Поскольку первая рука совпадает, никакие другие руки не сравниваются.

Объединение match и перечислений полезно во многих ситуациях.Вы часто увидите этот шаблон в коде Rust: match для перечисления, свяжите переменную с данными внутри, а затем выполните код на его основе.Сначала это немного сложно, но как только вы к этому привыкнете, вам захочется, чтобы оно было на всех языках.Это неизменно любимый пользователь.

...