Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Rough draft to automatically generate infrastructure. This enables easier method chaining as an alternative for named arguments
/// Method 1: just a fn, corresponds roughly to using named parameters
fn foo(bar: u64) -> u64 {
println!("used foo(bar: u64) -> u64");
bar
}
/// Method 2: manually implementing a struct + impl
struct Foo {
pub bar: u64,
}
impl Foo {
pub fn new() -> Foo { Foo { bar: 0 } }
pub fn bar(mut self, val: u64) -> Self {
self.bar = val;
self
}
}
/// Method 3: using macro_rules! to cut the boilerplate
macro_rules! setter {
{ $name:ident : $_type:ty } => {
#[allow(unused)]
pub fn $name(mut self, value: $_type) -> Self {
self.$name = value;
self
}
};
}
macro_rules! gen {
{$struct_name:ident, $($field_name:ident = $field_value:expr, as $field_type:ty),+ } => {
struct $struct_name {
$($field_name : $field_type),+
}
impl $struct_name {
#[allow(unused)]
pub fn new() -> $struct_name {
$struct_name {
$($field_name: $field_value),+
}
}
$(setter! { $field_name : $field_type })+
}
}
}
fn main() {
// using method 1:
let bar0 = foo(100);
println!("bar0 = {}", bar0);
// using method 2
let foo1 = Foo::new()
.bar(200);
println!("bar1 = {}", foo1.bar);
// using method 3: macros
// First, generate infrastructure.
// Note how it has been reduced to 1 rather descriptive call,
// rather than being swaths of boilerplate.
// Having to specify the type may be either a rough patch
// or a feature, depending on what you want out of it.
gen! { GenFoo,
bar = 0, as u64 ,
baz = "Hi I'm baz", as &'static str
};
let gen_foo = GenFoo::new()
.bar(9001);
println!("bar2 = {}", gen_foo.bar);
println!("baz = {}", gen_foo.baz);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.