Что Some () делает в левой части присваивания переменной? - PullRequest
0 голосов
/ 23 декабря 2018

Я читал некоторый код Rust и наткнулся на эту строку

if let Some(path) = env::args().nth(1) {

Внутри этой функции

fn main() {
    if let Some(path) = env::args().nth(1) {
        // Try reading the file provided by the path.
        let mut file = File::open(path).expect("Failed reading file.");
        let mut content = String::new();
        file.read_to_string(&mut content);

        perform_conversion(content.as_str()).expect("Conversion failed.");
    } else {
        println!(
            "provide a path to a .cue file to be converted into a MusicBrainz compatible tracklist."
        )
    }
}

Строка, кажется, присваивает аргумент envпеременный путь, но я не могу понять, что делает Some() вокруг него.

Я взглянул на документацию для Option, и я понимаю, как она работает при использованиис правой стороны от =, но с левой стороны я немного запутался.

Прав ли я, думая, что эта строка эквивалентна

if let path = Some(env::args().nth(1)) {

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

Другие ответы вошли во многие детали, которые могут быть больше, чем вам нужно знать.

По сути, это:

if let Some(path) = env::args().nth(1) {
    // Do something with path
} else {
    // otherwise do something else
}

идентично на это:

match env::args().nth(1) {
    Some(path) => { /* Do something with path */ }
    _          => { /* otherwise do something else */ }
}
0 голосов
/ 23 декабря 2018

Из ссылки :

Выражение if let семантически похоже на выражение if, но вместо выражения условия оно ожидает ключевое слово let, за которым следует опровержимый шаблон., = и выражение.Если значение выражения в правой части = соответствует шаблону, будет выполнен соответствующий блок, в противном случае поток переходит к следующему блоку else, если он существует.Подобно выражениям if, если выражения let имеют значение, определяемое оцениваемым блоком.

Здесь важной частью является refability .Что значит опровержимая картина, здесь она может быть в разных формах.Например:

enum Test {
    First(String, i32, usize),
    Second(i32, usize),
    Third(i32),
}

Вы можете проверить значение x для значения для 3 различных шаблонов, например:

fn main() {
    let x = Test::Second(14, 55);
    if let Test::First(a, b, c) = x {}
    if let Test::Second(a, b) = x {} //This block will be executed
    if let Test::Third(a) = x {}
}

Это называется refability .Но рассмотрим ваш код следующим образом:

enum Test {
    Second(i32, usize),
}

fn main() {
    let x = Test::Second(14, 55);
    if let Test::Second(a, b) = x {}
}

Этот код не будет компилироваться, поскольку шаблон x очевиден, он имеет один шаблон.Вы можете получить дополнительную информацию из справочника об опровержимости .

Также вы не правильно думаете об этом:

if let path = Some(env::args().nth(1)) {

Компилятор выдаст ошибку, такую ​​как неопровержимаяшаблон if-let , потому что, как указано в ссылке, «ключевое слово let сопровождается опровержимым шаблоном».Здесь нет опровержимой картины после «пусть».На самом деле этот код пытается создать переменную с именем path, которая является Option, и это не имеет никакого смысла, потому что нет необходимости " Если ",

Вместо этого Rust ожидает от вас такой записи:

let path = Some(env::args().nth(1)); // This will be seem like Some(Some(value))
...