【问题标题】:Possible in Rust to perform captures for block expressions?可以在 Rust 中执行块表达式的捕获吗?
【发布时间】:2020-09-13 04:17:33
【问题描述】:

我的意思的那种事情的简单例子:

let x = 10;
if true {
    let x = 20;
}
println!("x is {}", x);

这将打印x is 10,而不是x is 20,并给我一个未使用的变量警告,因为if 块中的x 与它外面的x 不同。有没有办法可以对 if 执行类似捕获的操作,以便它实际作用于包含块的 x

我在这里想象通过重复的let 语句来执行遮蔽是可取的,但如果它只是一个int,这个例子会更简洁。在伪代码中,可能更像是:

let data = get_data_from_user();
let data = initial_processing(data);
let data = further_processing(data);
if some_condition {
    let data = conditional_processing(data);
} else {
    let data = fallback_processing(data);
}

(也许答案是这是代码异味,我应该将if some_condition 检查移到conditional_processing 函数调用中。)

例如,对可重现示例的一种可能的重写:

let mut x = 10;
if true {
    x = 20;
}

我认为这与我的想法相差太大。

可以写

let x = 10;
let mut y = x;
if true {
    y = 20;
}
let x = y;
println!("x is {}", x);

所以x 最终成为设置为20 的非可变变量,尽管以引入一次性中间可变变量y 为代价。但是我仍然很好奇是否可以通过让if 块捕获并故意在其外部隐藏一个变量来实现这一点。

【问题讨论】:

    标签: rust expression shadowing


    【解决方案1】:

    已更新(请参阅下面的原始答案)

    你可能感兴趣

    let data = get_data_from_user();
    let data = initial_processing(data);
    let data = further_processing(data);
    let data = if some_condition {
        conditional_processing(data)
    } else {
        fallback_processing(data)
    };
    

    或者如果您想为 else 保留相同的值

    let x = 10;
    let x = if true {
        20
    } else {
        x
    }
    

    原答案

    不,这不可能。

    • 您不能强制变量在定义块之外可见。所以let x = <...> 不起作用。
    • 您不能更改不可变变量的值。所以x = <...> 不起作用。
    • 没有其他方法可以为变量赋值。

    【讨论】:

    • 尽管您可能会补充说,通常的解决方案是以不同的方式调用每个变量(甚至可能比data 更具描述性)或使变量可变。将块中的最终值返回到不可变变量也可能是一种选择。
    • @L.Riemer,感谢您的评论。从块中返回一个值是一个绝妙的主意。我相应地更新了我的答案。
    【解决方案2】:

    您可以通过重新绑定相同的变量来实现。

    // first step, prepare x as mutable
    let mut x = 10;
    if true {
        x = 20;
    }
    let x = x; // new binding for x
    // from now on, x is immutable
    

    表达相同想法的更常见(或可读)方式:

    let x = {
        // prepare a mutable x just inside this block
        let mut x = 10;
        if true {
           x = 20;
        }
        x // the result of this whole block
    };
    // in this scope, x is immutable
    

    这两种结构的共同点是你开始 使用可变绑定来初始化多个值 步骤,然后当它完成后,你切换到一个不可变的绑定 相同的值,以防止意外 变异它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-11
      • 2014-09-09
      • 2017-01-01
      • 2022-01-08
      • 1970-01-01
      • 2017-01-17
      • 1970-01-01
      相关资源
      最近更新 更多