I\'m trying to write a macro that generates a struct. The implementation for the struct will be generated by the macro, but some blocks of code will be provided as macro argumen
You can pass a closure instead of a block.
make_struct!(Test |this| println!("Foo: {:?}", this.foo));
Then the macro can use the closure and call it with self
:
macro_rules! make_struct {
($name:ident $closure:expr) => {
struct $name {
foo: i32,
}
impl $name {
fn new() -> Self {
$name { foo: 42 }
}
fn act (&self) {
let x: &Fn(&Self) = &$closure;
x(self)
}
}
};
}
The dance with the let binding is necessary, because the type of this
in the closure can't be inferred (yet?). And it also makes your macro's error reporting a little more readable when something other than a closure is passed.
Found a way to do it by adding a parameter to the macro that stores the name by which self
will be accessed in the blocks:
macro_rules! make_struct {
($myname:ident : $type_name:ident $block:block) => {
struct $type_name {
foo: i32,
}
impl $type_name {
fn new() -> Self {
$type_name { foo: 42 }
}
fn act (&self) {
let $myname = self;
$block
}
}
};
}
fn main() {
make_struct!(myself: Test { println! ("Foo: {:?}", myself.foo); });
let test = Test::new();
test.act();
}