【问题标题】:Using macros so that you don't have to write down a long parameter list every time使用宏,这样您就不必每次都写下长长的参数列表
【发布时间】:2021-12-31 15:54:12
【问题描述】:

假设我有一个大函数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 '&lt;', found 'defaultParams'

PS:我知道在这个特定的示例中,即使没有宏,代码看起来也很干净。但实际上,我正在使用的代码有点复杂,如果每次都完整地写下参数/参数列表,那么看起来会一团糟。子函数本身也会有子子函数,这也需要参数列表。

【问题讨论】:

  • 我会说将所有数据捆绑在一个结构中将是最干净的解决方案,但如果您更愿意追求宏观策略,我相信您必须将整个函数包装在宏中为了添加参数,即使如此,由于宏卫生,我不确定您是否可以在不将它们的标识符作为输入传递给宏的情况下访问这些参数。

标签: rust substitution rust-macros


【解决方案1】:

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) {
    /* ... */
}

}

Playground.

你能做的就是把它们收集到一个共享的地方,但我几乎可以肯定这需要咀嚼。你可以这样做,但不要这样做。

正确的做法肯定是将它们收集到一个结构中,也许也可以制作 fns 成员函数。

编辑: For completeness sake, here's a tt-muncher that does what you want.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-27
    • 2017-06-22
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    相关资源
    最近更新 更多