7 个不稳定版本 (3 个破坏性更新)
0.4.3 | 2022年7月28日 |
---|---|
0.4.2 | 2022年7月28日 |
0.4.1 | 2022年5月10日 |
0.3.0 | 2021年12月24日 |
0.1.0 | 2021年12月24日 |
501 在 过程宏 中
18KB
250 行
mwt
嘿!你!在使用前阅读此内容!
mwt是为了个人使用而迅速拼凑起来的,因为我找不到一个现有的crate可以做到这一点。
我已经使用它几个月了,还没有遇到任何重大问题,但可能存在一些错误。
肯定有一些边缘情况还没有被考虑,错误信息也比较糟糕。
随着我使用它并修复我发现的问题,它应该会得到改善,但“买者自慎”或其他什么
在不重复代码的情况下生成相同函数的mut和非mut版本!
mwt提供了两个基本相同的宏:mwt
和 maybe_mut
mwt
在标识符中寻找mwt
,并寻找类似&Mwt<T>
的类型maybe_mut
对maybe_mut
和&MaybeMut<T>
做同样的事情
它们都允许你在块之前放置 #[if_mut]
和 #[not_mut]
来有条件地包含部分。
它们还有分别对应的 mwt()
和 maybe_mut()
函数,用于类似 return &mwt(self.0)
的操作。
两者都允许您传递一个参数 ignore_self
,例如:#[mwt::maybe_mut(ignore_self)]
以阻止 mwt 修改 &self
(或 &mut self
)参数。从 &mut self
中移除 mut
是默认行为,因为取 &T<self>
会导致解析错误,而且在大多数情况下,这是期望的行为(至少在我的用例中)。
目前尚无处理形式为 _ref
/_mut
的函数的方法,但将来可能会添加(可能是 rwf
,它将变为 ref
或 mut
?)
*这不是一个函数,但过程宏会像函数调用一样寻找它的使用
示例
mwt 允许您编写
use mwt::mwt;
struct SomeStruct {
a_vector: Vec<SomeStruct>,
}
impl SomeStruct {
#[mwt]
fn my_mwt_accessor(&mut self) -> &Mwt<SomeStruct> {
let mut a = 0;
a = a + 1;
let b = &mwt(a);
#[if_mut] {
println!("Hello from my_mut_accessor()!");
}
#[not_mut] {
println!("Hello from my_accessor()!");
}
self.a_vector.get_mwt(0).unwrap()
}
}
这将生成两个函数
impl SomeStruct {
fn my_accessor(&self) -> &SomeStruct {
let mut a = 0;
a = a + 1;
let b = &a;
println!("Hello from my_accessor()!");
self.a_vector.get(0).unwrap()
}
fn my_mut_accessor(&mut self) -> &mut SomeStruct {
let mut a = 0;
a = a + 1;
let b = &mut a;
println!("Hello from my_mut_accessor()!");
self.a_vector.get_mut(0).unwrap()
}
}
如何使用
例如:
#[mwt::mwt]
fn my_mwt_method(&'a mut self, other_param: i32) -> &Mwt<bool> {
#[if_mut] {
//code for only the mut version of the function
let i = 0;
}
#[not_mut] {
// code for only the non-mut version of the function
let i= 1;
}
// do something with i
self.get_mwt_flag_by_index(i)
}
基本上,编写您函数的可变版本,但对于标识符,将 mut
替换为 mwt
,对于类型,将 &mut T
替换为 &Mwt<T>
您还可以在类型中使用 Mwt
,例如 MyMwtType
变为 MyMutType
和 MyType
或者,如果您觉得更易读,可以使用 mwt::maybe_mut
。示例
#[mwt::maybe_mut]
pub fn get_maybe_mut<T: 'static + Component>(&mut self) -> Option<&MaybeMut<T>> {
// use #[if_mut]{} and #[not_mut]{} for conditional behavior
// or for cases where mwt isn't powerful enough yet
// like .as_ref() vs .as_mut()
#[if_mut] { println!("if_mut"); }
#[not_mut] { println!("not_mut"); }
// use &MaybeMut<T> for &mut types
let map: &MaybeMut<HashMap<TypeId,Box<dyn Component>>>
// and &maybe_mut(...) for taking mut references
= &maybe_mut(self.components);
// use _maybe_mut_ in function calls, etc.
map.get_maybe_mut(&TypeId::of::<T>())
.and_then(|c| c.cast_maybe_mut::<T>())
}
生成两个函数
pub fn get_<T: 'static + Component>(& self) -> Option<&T> {
println!("not_mut");
let map: &HashMap<TypeId,Box<dyn Component>> = &self.components;
map.get(&TypeId::of::<T>()).and_then(|c| c.cast::<T>())
}
pub fn get_mut<T: 'static + Component>(&mut self) -> Option<&mut T> {
println!("if_mut");
let map: &mut HashMap<TypeId,Box<dyn Component>> = &mut self.components;
map.get_mut(&TypeId::of::<T>()).and_then(|c| c.cast_mut::<T>())
}
它实际上做了什么?
mwt::mwt
基本上只是将函数替换为两个副本(即非可变和可变版本),并在这些副本上执行一些操作
- 将所有类型引用,如
&Mwt<T>
,替换为&T
和&mut T
分别 - 将所有
mwt(expr)
替换为expr
和mut expr
分别 - 对于函数的非可变版本
- 它取找到的所有标识符,删除任何以 "mwt_" 开头和以 "_mwt" 结尾的部分,并将 "_mwt_" 替换为 "_"
- 它取找到的所有类型,删除任何 "Mwt" 实例
- 对于函数的可变版本
- 它取找到的所有标识符,将任何 "mwt" 实例替换为 "mut"
- 它取找到的所有类型,将任何 "Mwt" 实例替换为 "Mut"
- 为了允许行为有其他差异的方式,mut版本移除任何
#[not_mut]{...}
的出现,而非mut版本移除任何#[if_mut]{...}
的出现(未被移除的会移除花括号,请注意这一点) - 为了允许不同类型,
MwtAlt<First, Second>
在mut和非mut版本中分别被替换为First
或Second
mwt::maybe_mut
只是字符串不同,含义相同。(Mwt
-> MaybeMut
,mwt
-> maybe_mut
,MwtAlt
-> MutOrElse
)
发现了bug?需要功能?
请提交一个问题或发送一个pull request!
依赖项
~1.5MB
~35K SLoC