我有这段代码:
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
}
可以实现这样的可读性吗?
答案 0 :(得分: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.0
和x
更改相同的值。这在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;
}