如何使用Rust宏避免子函数定义调用时重复编写长参数列表
错误原因
你遇到的编译错误是Rust的语法解析顺序导致的:宏展开发生在语法解析之后,当编译器解析函数参数列表时,会把defaultParams!()识别为参数名,而参数名后必须跟:和类型,不符合语法规则,因此抛出错误。
下面提供两种可行的实现方案:
方案1:公共参数打包为上下文结构体(最推荐,符合Rust最佳实践)
这种方案不需要宏,易读易维护,IDE支持度高,多级传递也非常方便:
// 定义上下文结构体,封装所有公共参数 struct GameContext { mainDeck: Vec<Card>, dealer: Participant, players: Vec<Participant>, } fn A() { // 初始化上下文 let mut ctx = GameContext { mainDeck: Vec::new(), dealer: Participant::new(), players: Vec::with_capacity(4), }; let extraArgument = 21; // 调用子函数只需要传上下文即可 shuffleDeckAndDealFirstCards(&mut ctx); playGame(&mut ctx, extraArgument); evaluateWinner(&mut ctx); payout(&mut ctx); } // 子函数定义只需要一个上下文参数 fn shuffleDeckAndDealFirstCards(ctx: &mut GameContext) { // 内部使用直接访问ctx的字段即可:ctx.mainDeck、ctx.dealer、ctx.players } fn playGame(ctx: &mut GameContext, extraArgument: i32) { // 函数逻辑 }
如果不想要每次写ctx.前缀,可以在函数开头加变量绑定:
fn shuffleDeckAndDealFirstCards(ctx: &mut GameContext) { let GameContext { mainDeck, dealer, players } = ctx; // 接下来可以直接用mainDeck、dealer、players变量 }
方案2:宏实现你要的简化写法
如果你确实需要和你示例完全一致的写法,可以用两个宏分别处理函数定义和调用场景:
第一步:定义两个宏
// 用于调用时生成公共实参列表,可直接放在函数调用的参数中 macro_rules! default_args { () => { &mut mainDeck, &mut dealer, &mut players }; } // 用于定义子函数,自动生成公共参数列表 macro_rules! def_game_fn { (fn $fn_name:ident ( $( $extra_param:tt )* ) $body:block ) => { fn $fn_name( mainDeck: &mut Vec<Card>, dealer: &mut Participant, players: &mut Vec<Participant>, $( $extra_param )* ) $body }; }
第二步:使用宏编写代码
fn A(){ let mut mainDeck = Vec::<Card>::new(); let mut dealer = Participant::new(); let mut players : Vec<Participant> = Vec::with_capacity(4); let extraArgument = 21; // 调用和你示例的写法完全一致 shuffleDeckAndDealFirstCards(default_args!()); playGame(default_args!(), extraArgument); evaluateWinner(default_args!()); payout(default_args!()); } // 定义子函数用def_game_fn宏包裹 def_game_fn! { fn shuffleDeckAndDealFirstCards() { /* 函数体内直接使用mainDeck、dealer、players即可 */ } } def_game_fn! { fn playGame(extraArgument : i32) { /* 函数逻辑 */ } } def_game_fn! { fn evaluateWinner() { /* 函数逻辑 */ } } def_game_fn! { fn payout() { /* 函数逻辑 */ } }
这种写法完全匹配你想要的简化效果,调用时不需要重复写三个公共参数,定义时也只需要写额外参数即可。
内容的提问来源于stack exchange,提问作者INEEDANSWERS
相关产品推荐
相关产品推荐

