使用宏,这样您就不必每次都写下很长的参数列表
Using macros so that you don't have to write down a long parameter list every time
假设我有一个大函数 A
。作为一种组织方式,我将其拆分为多个子功能。所有这些都依赖于 A
初始化和提供的一对标准变量。有没有一种方法可以使用宏,而不是每次调用和定义一个这样的子函数时都写出所有这些参数列表和参数列表?
例如:代入这个:
fn A(){
let mut mainDeck = Vec<Card>;
let mut dealer = Participant::new();
let mut players : Vec<Participant> = Vec::with_capacity(4);
let extraArgument = 21;
shuffleDeckAndDealFirstCards(&mut mainDeck, &mut dealer, &mut players);
playGame(&mut mainDeck, &mut dealer, &mut players, extraArgument);
evaluateWinner(&mut mainDeck, &mut dealer, &mut players)
payout(&mut mainDeck, &mut dealer, &mut players); }
fn shuffleDeckAndDealFirstCards(
mainDeck : &mut Vec<Card>,
dealer : &mut Participant,
players : &mut Vec<Participant> ){
/* ... */ }
fn playGame(
mainDeck : &mut Vec<Card>,
dealer : &mut Participant,
players : &mut Vec<Participant>,
extraArgument : i32 ){
/* ... */ }
fn evaluateWinner(
mainDeck : &mut Vec<Card>,
dealer : &mut Participant,
players : &mut Vec<Participant> ){
/* ... */ }
fn payout(
mainDeck : &mut Vec<Card>,
dealer : &mut Participant,
players : &mut Vec<Participant> ){
/* ... */ }
为此:
fn A(){
let mut mainDeck = Vec<Card>;
let mut dealer = Participant::new();
let mut players : Vec<Participant> = Vec::with_capacity(4);
let extraArgument = 21;
shuffleDeckAndDealFirstCards(defaultArgs!());
playGame(defaultArgs!(), extraArgument);
evaluateWinner(defaultArgs!())
payout(defaultArgs!());
}
fn shuffleDeckAndDealFirstCards(defaultParams!()){
/* ... */
}
fn playGame(defaultParams!(), extraArgument : i32){
/* ... */
}
fn evaluateWinner(defaultParams!()){
/* ... */
}
fn payout(defaultParams!()){
/* ... */
}
我尝试使用如下所示的简单宏:
macro_rules! defaultParams {
() => {
mainDeck : &mut deck_t,
dealer : &mut dealer,
players : &Vec<Participant>
};
}
但是当我在一个函数上尝试它时:
fn shuffleDeckAndDealFirstCards(defaultParams!()){
/* ... */
}
它给出错误:expected one of '(' or '<', found 'defaultParams'
PS:我知道在这个特定示例中,即使没有宏,代码看起来也很干净。但实际上,我正在使用的代码有点复杂,如果 parameter/argument 列表每次都被完整地写下来,看起来会很乱。子函数本身也会有子子函数,这也需要参数列表。
Macros can only expand to whole items。所以,不,你不能。
但即使您像评论中所建议的那样用宏包装整个函数,您也会坚持卫生。您的代码中不能使用宏生成的标识符。例如:
// This macro does not accept all valid Rust fn declarations
macro_rules! with_default_params {
{
$(
fn $name:ident( $( $arg_name:ident : $arg_type:ty ),* $(,)? )
$( -> $ret_type:ty )?
$body:block
)*
} => {
$(
fn $name(
main_deck: &mut Deck,
dealer: &mut Dealer,
players: &Vec<Participant>,
$( $arg_name : $arg_type ),*
) $( -> $ret_type )?
$body
)*
};
}
with_default_params! {
fn shuffle_deck_and_deal_first_cards() {
let _ = main_deck; // Error
}
fn play_game(extra_argument: i32) {
/* ... */
}
}
你可以做的是将它们收集到一个共享的地方,但我几乎可以肯定这需要 tt-munching。你可以这样做,但不要这样做。
正确的做法肯定是将它们收集到一个结构中,也许也使 fns 成员函数。
编辑: For completeness sake, here's a tt-muncher that does what you want.
假设我有一个大函数 A
。作为一种组织方式,我将其拆分为多个子功能。所有这些都依赖于 A
初始化和提供的一对标准变量。有没有一种方法可以使用宏,而不是每次调用和定义一个这样的子函数时都写出所有这些参数列表和参数列表?
例如:代入这个:
fn A(){
let mut mainDeck = Vec<Card>;
let mut dealer = Participant::new();
let mut players : Vec<Participant> = Vec::with_capacity(4);
let extraArgument = 21;
shuffleDeckAndDealFirstCards(&mut mainDeck, &mut dealer, &mut players);
playGame(&mut mainDeck, &mut dealer, &mut players, extraArgument);
evaluateWinner(&mut mainDeck, &mut dealer, &mut players)
payout(&mut mainDeck, &mut dealer, &mut players); }
fn shuffleDeckAndDealFirstCards(
mainDeck : &mut Vec<Card>,
dealer : &mut Participant,
players : &mut Vec<Participant> ){
/* ... */ }
fn playGame(
mainDeck : &mut Vec<Card>,
dealer : &mut Participant,
players : &mut Vec<Participant>,
extraArgument : i32 ){
/* ... */ }
fn evaluateWinner(
mainDeck : &mut Vec<Card>,
dealer : &mut Participant,
players : &mut Vec<Participant> ){
/* ... */ }
fn payout(
mainDeck : &mut Vec<Card>,
dealer : &mut Participant,
players : &mut Vec<Participant> ){
/* ... */ }
为此:
fn A(){
let mut mainDeck = Vec<Card>;
let mut dealer = Participant::new();
let mut players : Vec<Participant> = Vec::with_capacity(4);
let extraArgument = 21;
shuffleDeckAndDealFirstCards(defaultArgs!());
playGame(defaultArgs!(), extraArgument);
evaluateWinner(defaultArgs!())
payout(defaultArgs!());
}
fn shuffleDeckAndDealFirstCards(defaultParams!()){
/* ... */
}
fn playGame(defaultParams!(), extraArgument : i32){
/* ... */
}
fn evaluateWinner(defaultParams!()){
/* ... */
}
fn payout(defaultParams!()){
/* ... */
}
我尝试使用如下所示的简单宏:
macro_rules! defaultParams {
() => {
mainDeck : &mut deck_t,
dealer : &mut dealer,
players : &Vec<Participant>
};
}
但是当我在一个函数上尝试它时:
fn shuffleDeckAndDealFirstCards(defaultParams!()){
/* ... */
}
它给出错误:expected one of '(' or '<', found 'defaultParams'
PS:我知道在这个特定示例中,即使没有宏,代码看起来也很干净。但实际上,我正在使用的代码有点复杂,如果 parameter/argument 列表每次都被完整地写下来,看起来会很乱。子函数本身也会有子子函数,这也需要参数列表。
Macros can only expand to whole items。所以,不,你不能。
但即使您像评论中所建议的那样用宏包装整个函数,您也会坚持卫生。您的代码中不能使用宏生成的标识符。例如:
// This macro does not accept all valid Rust fn declarations
macro_rules! with_default_params {
{
$(
fn $name:ident( $( $arg_name:ident : $arg_type:ty ),* $(,)? )
$( -> $ret_type:ty )?
$body:block
)*
} => {
$(
fn $name(
main_deck: &mut Deck,
dealer: &mut Dealer,
players: &Vec<Participant>,
$( $arg_name : $arg_type ),*
) $( -> $ret_type )?
$body
)*
};
}
with_default_params! {
fn shuffle_deck_and_deal_first_cards() {
let _ = main_deck; // Error
}
fn play_game(extra_argument: i32) {
/* ... */
}
}
你可以做的是将它们收集到一个共享的地方,但我几乎可以肯定这需要 tt-munching。你可以这样做,但不要这样做。
正确的做法肯定是将它们收集到一个结构中,也许也使 fns 成员函数。
编辑: For completeness sake, here's a tt-muncher that does what you want.