我正在尝试在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中的函数和不安全代码复制。
(这是一个有点人为的示例,如果有人感兴趣,我很乐意提供一个真实的示例。我在这里问的是核心思想。)
除了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协调(至今)。