rust - 有条件地捕获闭包中的变量以实现自定义控制
问题描述
我正在尝试在 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 中使用函数和不安全代码进行复制。
(这是一个稍微做作的例子,如果有人感兴趣,我很乐意提供真实的例子。我在这里问的是核心思想。)
解决方案
除了 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 协调(还)。
推荐阅读
- php - 规则错误的连接被拒绝和访问禁止,如何解决?
- google-apps-marketplace - 查找使用 C# 在 Sheets API 中创建的 google.sheet 文件
- swiftui - 如何在字体前面添加间距
- mongodb - 在 docker 容器中恢复 mongo 转储返回“失败:EOF”
- python - 如果满足条件,则在数据框中返回索引(日期)和列标题的方法
- discord.js - 在 nodejs [discord.js] 中从 args 运行 python
- arrays - 如何将 2 组数据合并到一个 UITableview 中
- c# - 我可以将泛型类与泛型方法一起使用吗?
- excel - 将 XLSM 文件导出为 PDF 而不切断的宏
- c# - textchanged 的应用程序页面文本框事件