【问题标题】:Conditionally capture variables in closure to implement custom control [duplicate]有条件地捕获闭包中的变量以实现自定义控件[重复]
【发布时间】:2020-01-31 20:25:00
【问题描述】:

我正在尝试在 Rust 中实现自定义控制结构。例如,假设出于某种原因,我想将自定义 if 语句实现为函数。该函数将采用一个条件,一个代表真分支的闭包和一个代表假分支的闭包。根据情况,我会称真分支闭包或假分支闭包。

看起来像这样:

pub fn fun_if<O>(
    cond: bool,
    mut tbranch: impl FnMut() -> O,
    mut fbranch: impl FnMut() -> O,
) -> O {
    if cond {
        tbranch()
    } else {
        fbranch()
    }
}

这个实现的问题是真闭包不能可变地借用与假闭包相同的变量:

let mut test = 0;
fun_if(true, || test = 1, || test = 2)
                ^^^^         ^^^^ ! error !

然而,rustif 语句足够聪明,知道真假分支永远不会被调用在一起。下面的编译就好了:

let mut test = 0;
if true {
    test = 1
} else {
    test = 2
}

我的问题是 if 的行为是否可以在 rust 中使用函数和不安全代码进行复制。

(这是一个稍微做作的例子,如果有人感兴趣,我很乐意提供真实的例子。我在这里问的是核心思想。)

【问题讨论】:

    标签: rust unsafe


    【解决方案1】:

    除了 Stargateurs 链接,这在一般情况下是绝对正确的,我想指出这个特定的问题可以很容易地用宏解决。这是我对这个问题的看法。

    macro_rules! macro_if {
        ($cond:expr, $t:stmt, $f:stmt) => {
            if ($cond) {
                $t
            } else {
                $f
            }
        };
    }
    

    使用示例

    let return_val = macro_if!(
            !cond,
            {
                test = 1;
                0
            },
            {
                test = 2;
                5
            }
        );
    

    由于宏是在编译时进行评估的,因此该解决方案可以启用您的用例,同时仍保留 rust 编译器安全地推理您的代码的能力。虽然在这个简单的示例中使用 unsafe 可能是合理和正确的,但更复杂的情况可能会很快导致您的实现中出现不健全的错误。我们不希望这种情况发生。

    这种方法的缺点是它可能会破坏宏调用中的自动完成功能。至少对我来说,宏还不能与 rls 协调得很好(目前)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-19
      • 1970-01-01
      • 2021-02-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-23
      • 2020-09-20
      相关资源
      最近更新 更多