学习记录,都是学自圣经,macrobook啥的
https://doc.rust-lang.org/reference/macros-by-example.html
macro_rules! bar {
(3) => {
println!("3");
};
(4) => {
println!("4");
};
}
这个是入门例子,有点像match
调用就是bar!(xxxx)
bar!(3)会输出3这样
macro_rules! foo {
($input:tt) => {
bar!($input);
};
}
macro_rules! bar {
(3) => {
println!("3");
};
(4) => {
println!("4");
};
}
第二个例子,在第一个宏调用另外的宏,
这有个需要注意的地方,$input只有ident,tt,lifetime可以传递出去
然后还能正则表达式
macro_rules! vec_strs {
(
$(
$element:expr
)
,
*
) => {
{
let mut v = Vec::new();
$(
v.push(format!("{}", $element));
)*
v
}
};
}
fn main() {
let s = vec_strs![1, "a", true, 3.14159f32];
assert_eq!(s, &["1", "a", "true", "3.14159"]);
}
这个就是匹配括号里的内容多次并替换为后面的括号里的逻辑,然后把东西push进去vec
复杂一点的斐波那契数列,为Recurrence实现一个iterator
返回Recurrence 的那里,mem匹配多次inits得到0,1,
next_val 求值那里ind,seq的类型要ident才能通过
macro_rules! count_exprs {
() => (0);
($head:expr) => (1);
($head:expr, $($tail:expr),*) => (1 + count_exprs!($($tail),*));
}
macro_rules! recurrence {
( $seq:ident [ $ind:ident ]: $sty:ty = $($inits:expr),+ ; ... ; $recur:expr ) => {
{
use std::ops::Index;
const MEM_SIZE: usize = count_exprs!($($inits),+);
struct Recurrence {
mem: [$sty; MEM_SIZE],
pos: usize,
}
struct IndexOffset<'a> {
slice: &'a [$sty; MEM_SIZE],
offset: usize,
}
impl<'a> Index<usize> for IndexOffset<'a> {
type Output = $sty;
#[inline(always)]
fn index<'b>(&'b self, index: usize) -> &'b $sty {
use std::num::Wrapping;
let index = Wrapping(index);
let offset = Wrapping(self.offset);
let window = Wrapping(MEM_SIZE);
let real_index = index - offset + window;
&self.slice[real_index.0]
}
}
impl Iterator for Recurrence {
type Item = $sty;
#[inline]
fn next(&mut self) -> Option<$sty> {
if self.pos < MEM_SIZE {
let next_val = self.mem[self.pos];
self.pos += 1;
Some(next_val)
} else {
let next_val = {
let $ind = self.pos;
let $seq = IndexOffset { slice: &self.mem, offset: $ind };
$recur
};
{
use std::mem::swap;
let mut swap_tmp = next_val;
for i in (0..MEM_SIZE).rev() {
swap(&mut swap_tmp, &mut self.mem[i]);
}
}
self.pos += 1;
Some(next_val)
}
}
}
Recurrence { mem: [$($inits),+], pos: 0 }
}
};
}
fn main() {
let fib = recurrence![a[n]: u64 = 0, 1; ...; a[n-2] + a[n-1]];
for e in fib.take(10) { println!("{}", e) }
}
理解下来基本用法就是这个,匹配替换,但是还需要深入理解一下各种metavariable究竟怎么定义的