温馨提示:本文翻译自stackoverflow.com,查看原文请点击:rust - Conditionally capture variables in closure to implement custom control
rust unsafe

rust - 有条件地捕获闭包中的变量以实现自定义控件

发布于 2020-04-08 00:01:35

我正在尝试在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 !

但是,rust if语句足够聪明,可以知道将永远不会一起调用true和false分支。以下编译就可以了:

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

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

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

查看更多

提问者
Sam Thomas
被浏览
120
L. Riemer 2020-02-02 04:26

除了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在此简单示例中使用migth是合理且正确的,但更复杂的情况可能会很快导致实现中的错误。我们不希望这种情况发生。

这种方法的缺点是,它可能破坏了宏调用内的自动完成功能。至少对我来说,宏还不能很好地与rl协调(至今)。