Rust元组赋值

4

我有以下情况:

use num_bigint::BigUint;

fn add_one(px: BigUint, py: BigUint) -> (BigUint, BigUint) {
    (px+1u32, py+1u32)
}

fn test(x: &[u8], y: &[u8]) {
    let mut x = BigUint::from_bytes_le(x);
    let mut y = BigUint::from_bytes_le(y);

    (x,y) = add_one(x, y);
}

当我尝试编译时,出现以下编译错误:

error[E0658]: destructuring assignments are unstable
  --> src/lib.rs:76:11
   |
76 |     (x,y) = ecc_add(x, y);
   |     ----- ^
   |     |
   |     cannot assign to this expression
   |
   = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information

这是什么意思?let (x,y) = add_one(x, y); 似乎解决了错误,但我认为这不会改变原始的 xy 变量(?),而且我想避免创建任何临时变量。当我使用 (x, y) = (x+1u32, y+1u32); 时,我得到相同的错误。
如果我改用单个返回值,则可以正常工作:
use num_bigint::BigUint;

fn add_one(px: BigUint) -> BigUint {
    px+1u32
}

fn test(x: &[u8]) {
    let mut x = BigUint::from_bytes_le(x);

    x = add_one(x)
}

我该如何将xy赋值为add_one的返回值?
4个回答

6

像这样的解构赋值是不稳定的特性,容易发生变化和被移除,因此你不能在稳定的Rust中使用它。

只需使用let (x,y) = ...。 "太多临时变量"不是您应该担心的问题(至少没有进行分析),特别是旧的xy变量已经被移出。让编译器去处理重用空间的问题;它可以做得比你更好。


完全同意。特别是在 Rust 中,拥有大量的本地变量是完全正常的,并且比跟踪单个变量的修改要好得多。就编译器而言,SSA 风格的变量使用可能比在各处跟踪显式变异更容易进行优化。 - Silvio Mayolo

2

1

使用嵌套作用域中的元组

在撰写本文时,解构赋值仍然是一个不稳定的功能,这意味着您不能像下面这样设置x和y元组的值:

let x: String;

let y: String;

(x, y) = (String::from("red"), String::from("fire"));

你需要像这样使用let(x, y):

let (x, y) = (String::from("red"), String::from("fire"));

然而,在某些情况下,您希望在父范围中声明元组(以便您可以在同一范围内的后续代码中使用它),但是您希望元组值在嵌套范围(例如if语句)中设置。
在这些情况下,您不能在嵌套范围中使用let引用父范围中的元组值,因为let在嵌套范围中创建一个新元组,而不是使用/引用父范围中的元组。
但是,您仍然可以在嵌套范围中使用let创建新元组;然后只需在每个嵌套范围结束时将它们提升到父范围。
fn main() {

    let test_value = 1;

    // create (x1, y1) in outer scope
    let (x1, y1) = { 
        // create (x2, y2) in first nested scope
        let (x2, y2) = 
            if test_value == 1 {
                // create and set (x3, y3) in second nested scope
                let x3 = String::from("red"); 
                let y3 = String::from("fire");
                (x3, y3) // bump (x3, y3) values to (x2, y2) in first nested scope
            }
            else {
                panic!("Invalid value for test_value");
            };
        (x2, y2) // bump (x2, y2) values to (x1, y1) in outer scope
    };

    // Use the (x1, y1) values in the outer scope
    println!("x1: {:?} y1: {:?}", x1, y1);
}

总结

嵌套作用域中的代码可以引用父级作用域中创建的元组值,但无法更改它们的值。父级作用域必须使用 let 将其值从嵌套作用域中 拖出来,而嵌套作用域必须使用 bump 将新值传递给父级作用域 - 如上例所示。

总结 - 这是可编译的:

let (a1, b1) = (7, 5);

if a1 > b1{
    print!("{} is larger than {}", a1, b1);
}

总结 - 这段代码无法编译:
let (a1, b1) = (7, 5);

if a1 > b1{
    print!("{} is larger than {}", a1, b1);
    (a1, b1) = (10, 8);
}

总结一下 - 这个可以编译:
let (a1, b1) = (7, 5);
let (a1, b1) = 
    if 7 > 5{
        println!("{} is larger than {}", a1, b1); // original a1, b1 values
        (10, 20) // bump up new values to a1, b1
    }
    else { 
        // you need an else statement to make the entire if-statement deterministic,
        // otherwise you get expected...found errors
        panic!("What?");
    };
    
println!("a1: {:?} b1: {:?}", a1, b1); // new a1, b1 values

输出:

7比5大

a1:10 b1:20


0

你需要使用let进行解构(变量阴影是被允许和鼓励的)。

let (x, y) = add_one(x, y);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接