如何使用解构来可读地处理元组?

问题描述 投票:0回答:1

我有这个代码:

fn f(x: &mut (i32, i32)) -> &(i32, i32) {
    x.1 = x.1 + 11;
    x.0 = x.0 * 10;
    x
}

我会比较喜欢:

fn f((x, y) as t: &mut (i32, i32)) -> &(i32, i32) {
    x = x + 11;
    y = y * 10;
    t
}

可以实现这样的可读性吗?

rust
1个回答
4
投票

可以实现这样的可读性吗?

不,不是在当前的Rust或计划的未来。类似于您想要的语法:

fn f(t @ &mut (ref x, ref y): &mut (i32, i32)) -> &(i32, i32)

但是,不允许:

error[E0007]: cannot bind by-move with sub-bindings
 --> src/main.rs:3:6
  |
3 | fn f(t @ &mut (ref x, ref y): &mut (i32, i32)) -> &(i32, i32) {
  |      ^^^^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it

error[E0303]: pattern bindings are not allowed after an `@`
 --> src/main.rs:3:16
  |
3 | fn f(t @ &mut (ref x, ref y): &mut (i32, i32)) -> &(i32, i32) {
  |                ^^^^^ not allowed after `@`

error[E0303]: pattern bindings are not allowed after an `@`
 --> src/main.rs:3:23
  |
3 | fn f(t @ &mut (ref x, ref y): &mut (i32, i32)) -> &(i32, i32) {
  |                       ^^^^^ not allowed after `@`

这种代码的一个棘手的方面是你有可变的别名 - 你可以通过t.0x改变相同的值。这在Rust中是不允许的。

很有可能,备受期待的非词汇生命周期(NLL)可能允许编译器更好地推理这些案例,但我没有听到人们采取这个具体方面。


如果您愿意灵活,有一些选择:

fn f(t: &mut (i32, i32)) -> &(i32, i32) {
    {
        let &mut (ref mut x, ref mut y) = t;
        *x = *x + 11;
        *y = *y * 10;
    }
    t
}

在夜间Rust中,这可以简化:

#![feature(match_default_bindings)]

fn f(t: &mut (i32, i32)) -> &(i32, i32) {
    {
        let (x, y) = t;
        *x = *x + 11;
        *y = *y * 10;
    }
    t
}

据我了解,这两种情况都应该由NLL改进。

由于您正在获取并返回相同的值引用,因此您可以停止返回它:

fn f(&mut (ref mut x, ref mut y): &mut (i32, i32)) {
    *x = *x + 11;
    *y = *y * 10;
}

在夜间Rust中同样可以改进:

#![feature(match_default_bindings)]

fn f((x, y): &mut (i32, i32)) {
    *x = *x + 11;
    *y = *y * 10;
}
© www.soinside.com 2019 - 2024. All rights reserved.