Created
April 29, 2017 04:16
-
-
Save SpaceManiac/22c8505d92ef3b228fb41ec9694836ab to your computer and use it in GitHub Desktop.
rough kwargs macro sketch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::borrow::Cow; | |
#[macro_export] | |
macro_rules! kwargs { | |
// pass no arguments | |
() => { |_| {} }; | |
// in-progress variants | |
(@struct [$($attr:meta)*] $name:ident [$($decls:tt)*] $field:ident: $typ:ty, $($rest:tt)*) => { | |
kwargs!(@struct [$($attr)*] $name [$($decls)* $field: ::std::option::Option<$typ>,] $($rest)*); | |
}; | |
// version that does not end with a comma | |
(@struct [$($attr:meta)*] $name:ident [$($decls:tt)*] $field:ident: $typ:ty) => { | |
kwargs!(@struct [$($attr)*] $name [$($decls)* $field: ::std::option::Option<$typ>,]); | |
}; | |
// base case | |
(@struct [$($attr:meta)*] $name:ident [$($field:ident: $typ:ty,)*] $(,)*) => { | |
$(#[$attr])* | |
#[derive(Default)] | |
pub struct $name<'kw> { | |
$(pub $field: $typ,)* | |
__marker: ::std::marker::PhantomData<&'kw ()>, | |
} | |
}; | |
// resolve kwargs | |
(@resolve: $kw:ident) => { | |
{ let mut a = Default::default(); $kw(&mut a); a }; | |
}; | |
// declare kwargs receiver struct | |
($($(#[$attr:meta])* struct $name:ident { $($inner:tt)* };)*) => { | |
$(kwargs!(@struct [$($attr)*] $name [] $($inner)*);)* | |
}; | |
// pass some arguments, colon variant | |
($($field:ident: $value:expr),* $(,)*) => { | |
|x| { $(x.$field = Some(From::from($value));)* } | |
}; | |
} | |
// example usage | |
kwargs! { | |
#[doc(hidden)] | |
struct FooArgs { unused: u32, first: Cow<'kw, str>, second: &'kw str }; | |
} | |
pub fn foo<KW: FnOnce(&mut FooArgs)>(param: u32, kw: KW) { | |
let kwargs = kwargs!(@resolve: kw); | |
println!("param: {}", param); | |
println!(" first: {:?}", kwargs.first); | |
println!(" second: {:?}", kwargs.second); | |
} | |
fn main() { | |
foo(1, kwargs!(first: "First", second: "Second")); | |
//foo(2, kwargs!(second = "Second", first = "First".into())); | |
foo(3, kwargs!(first: "First")); | |
foo(4, kwargs!(second: "Second")); | |
foo(4, kwargs!()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment