1 个不稳定发布
0.1.0 | 2021 年 9 月 21 日 |
---|
#115 在 #capture
11KB
217 行
helper_fn
一个用于创建类似闭包的辅助函数的宏。
用法
此属性可以应用于函数项,允许它从父作用域继承变量。辅助函数必须在使用之前和继承的变量之后声明。
use helper_fn::helper_fn;
let mut num = 5;
#[helper_fn(num: i32)] // captures num from the surrounding scope
fn get_num() -> i32 {
num
}
assert_eq!(get_num!(), 5); // note that this is a macro invocation, not a function call
变量可以通过值(使用移动或复制语义)、通过引用或通过可变引用进行捕获
#[helper_fn(copied: i32, moved: Vec<i32>, &by_ref: Foo, &mut by_mut_ref: Bar)]
如果存在作用域问题,可以使用 use_helper_fn
宏
use helper_fn::{helper_fn, use_helper_fn};
let mut num = 5;
// hoist the definitions
use_helper_fn! {
get_num(num),
get_num_times_two(num) as get_num_times_2,
increment_num(&mut num),
};
assert_eq!(get_num!(), 5);
assert_eq!(get_num_times_2!(), 10);
increment_num!();
assert_eq!(get_num!(), 6);
assert_eq!(get_num_times_2!(), 12);
#[helper_fn(num: i32)]
fn get_num() -> i32 {
num
}
#[helper_fn(num: i32)]
fn get_num_times_two() -> i32 {
// reuse the definition from the parent scope
// has to be a different name to avoid conflict
use_helper_fn!(get_num(num) as get_num_);
get_num_!() * 2
}
#[helper_fn(&mut num: i32)]
fn increment_num() {
*num += 1;
}
理由
闭包经常用作需要周围作用域的辅助函数;以下是一个简单示例
let mut num = 5;
let get_num = || {
// Lots of complex stuff
num
};
assert_eq!(get_num(), 5);
这没问题,但如果在两次调用之间修改了 num
,则无法编译
let mut num = 5;
let get_num = || {
// Lots of complex stuff
num
};
assert_eq!(get_num(), 5);
num += 1; // cannot assign to `num` because it is borrowed
assert_eq!(get_num(), 6);
一种解决方案是在本地使用 fn
项并传递变量
let mut num = 5;
fn get_num(num: i32) -> i32 {
// Lots of complex stuff
num
}
assert_eq!(get_num(num), 5);
num += 1; // this is ok
assert_eq!(get_num(num), 6);
这可以工作,但如果有多个变量,可能会变得相当冗长。
使用 helper_fn
,您可以同时获得两者的优点
use helper_fn::helper_fn;
let mut num = 5;
#[helper_fn(num: i32)]
fn get_num() -> i32 {
num
}
assert_eq!(get_num!(), 5); // you don't need to pass in `num`
num += 1; // this is ok
assert_eq!(get_num!(), 6); // note that these calls are macro invocations
依赖关系
~1.5MB
~35K SLoC