Можно ли объявить переменную в условном выражении if в Rust?

В Go мы можем объявить переменную внутри условного выражения выражения if. Эта переменная будет действительна внутри области if, а не за ее пределами. Например:

func main() {
    if n := 4; n != 0 {
        fmt.Printf("%d is not zero", n)
    } else {
        fmt.Printf("%d is zero", n)
    }

    fmt.Printf("%d", n) // error, n doesn't exist here!
}

Есть ли подобный синтаксис в Rust?


person rodrigocfd    schedule 09.12.2020    source источник
comment


Ответы (3)


В Rust есть if let выражения:

if let n = 4 {}

println!("{}", n); // error: cannot find value `n` in this scope

Они в основном используются для сопоставления с образцом:

let optional_num = Some(1);

if let Some(num) = optional_num {
    println!("optional_num contained", num);
} else {
    println!("optional_num was None");
}

Существует RFC для if let chains что позволит сделать что-то вроде этого:

if let n = 4 && n != 0 {
    println!("{} is not zero", n);
}

println!("{}", n); // error, n doesn't exist here!

Однако переменные, объявленные в цепочках if let, относятся только к оператору if, а не к else, поэтому ваш пример невозможен:

if let n = 4 && n != 0 {
    println!("{} is not zero", n);
} else {
    println!("{}", n); // error, n doesn't exist here! 
}
person Ibraheem Ahmed    schedule 09.12.2020
comment
Я не думаю, что ваши утверждения о поведении цепочек if let верны, они не соответствуют обескураживанию, представленному в RFC, и не имеют большого смысла (поскольку это прямо не сработало бы, если бы шаблон был ошибочным и провалился ). - person Masklinn; 09.12.2020
comment
@Masklinn Спасибо, что указали на это, я обновил свой ответ. - person Ibraheem Ahmed; 09.12.2020

Я чувствую, что то, что вы пытаетесь сделать в своем коде, более точно соответствует оператору соответствия. Что-то вроде этого:

match 4 {
    n @ 0 => {
        println!("{} is zero", n);
    },
    
    n => {
        println!("{} is not zero", n);
    }
}

Или, в более общем смысле, если вы хотите протестировать произвольное логическое выражение, основанное на n:

match some_expression {
    n if some_boolean_function(n) => {
        println!("{} meets the requirements", n);
    },
    
    n => {
        println!("{} does not meet the requirements", n);
    }
}
person Benjamin Lindley    schedule 09.12.2020

Вы всегда можете определить новую область с помощью фигурных скобок:

fn main() {
    {
        let n = 4;
        if n != 0 {
            println!("{} is not zero", n);
        } else {
            println!("{} is zero", n);
        }
    }
    
    println!("{}", n); // error, n doesn't exist here!
}

Если вы достаточно сильно относитесь к этому, вы можете обернуть это в макрос:

macro_rules! thing {
    ($($s:stmt);+ , $e:expr) => {{
        $($s)+
        $e
    }};
}

fn main() {
    thing!(let n = 4, if n != 0 {
        println!("{} is not zero", n);
    } else {
        println!("{} is zero", n);
    });
    
    println!("{}", n); // error, n doesn't exist here!
}
person Shepmaster    schedule 09.12.2020