是否可以在 Rust 中的 if 表达式的条件中声明一个变量?

Is it possible to declare a variable in the conditional of an if expression in 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 中是否有类似的语法?

Rust 确实有 if let expressions:

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");
}

if let chains 有一个 RFC,它允许这样的事情:

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! 
}

我觉得您在代码中尝试做的事情更符合匹配语句。像这样:

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);
    }
}

您始终可以使用花括号定义新范围:

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!
}