首页 > 解决方案 > 如何制作递归宏来分解此代码?

问题描述

我试图制作一个分解一些代码的宏。

trait Animal {
    fn crie(&self) -> String;
    fn crie_plusieurs_fois(&self, n: isize) -> String {
        let mut res = "".to_string();
        if n > 0 {res = self.crie() + " " + &*res + &*self.crie_plusieurs_fois(n - 1) }
        res
    }
}

struct Chien {}
struct Chat {}

impl Animal for Chien {
    fn crie(&self) -> String {
        "wouaf".to_string()
    }
}


impl Animal for Chat {
    fn crie(&self) -> String {
        "miaou".to_string()
    }
}

我有这个,我想创建这个:

enum Animals{
    CHIEN(Chien),
    CHAT(Chat)
}

impl Animal for Animals{
    fn crie(&self) -> String {
        match self {
            Animals::CHIEN(c) => c.crie(),
            Animals::CHAT(c) => c.crie(),
        }
    }
}

使用这些递归宏:

macro_rules! impl_trait_for_enum{
    (
        $nom_trait: ident;

        $nom_enum: ident => $($nom_fonction:ident($($nom_var:ident : $type_var:ty),*) $(-> $type_retour:ty)?),+ ;

        $($identifiant : ident => $structure : ident),+
    ) => {

        enum $nom_enum{
            $($identifiant($structure)),+
        }

        impl $nom_trait for $nom_enum {
           impl_trait_function!($nom_enum; $($identifiant),+; $($nom_fonction ($($nom_var : $type_var),*) $(-> $type_retour)?),*);
        }
    }
}

macro_rules! impl_trait_function{
    (
        $nom_enum: ident;

        $($identifiant: ident ),*;

        $nom_fonction: ident($($nom_var:ident : $type_var:ty),*) $(-> $type_retour:ty)?,

        $($autre_nom_fonction: ident($($autre_nom_var:ident : $ autre_type_var:ty),*) $(-> $autre_type_retour:ty)?),*
    )=> {
        fn $nom_fonction(&self$(,$nom_var: $type_var),* ) $(-> $type_retour)? {
            match self {
                impl_multiple_pattern!($nom_enum;$nom_fonction($($nom_var),*); $($identifiant),*);
            }
        }
        impl_trait_function!($nom_enum; $($identifiant),+;
                            $($autre_nom_fonction ($($autre_nom_var : $ autre_type_var),*) $(-> $autre_type_retour)?),*);
    };
    ($nom_enum: ident; $($identifiant: ident),+;) => {}
}

macro_rules! impl_multiple_pattern {
    (
        $nom_enum: ident;

        $nom_fonction: ident($($nom_var: ident),*);

        $identifiant: ident,

        $($autre_identifiant: ident),*

    )=>{
        $nom_enum::$identifiant(s) => s.$nom_fonction($(nom_var: ident)*),
        impl_multiple_pattern($nom_enum; $nom_fonction($($nom_var)*); $rest);
    };

    (
        $nom_enum: ident;

        $nom_fonction: ident($($nom_var: ident)*);
    ) => {}


}

这个电话

impl_trait_for_enum!(  Animals; Animal => crie() -> String, crie_plusieur_fois(n: isize) -> String;
                        Dog => Chien,
                        Cat => Chat
                       );

我有这个错误:

error: expected one of `=>`, `if`, or `|`, found `;`
   --> src/main.rs:101:98
    |
101 |                   impl_multiple_pattern!($nom_enum;$nom_fonction($($nom_var),*); $($identifiant),*);
    |                                                                                                    ^ expected one of `=>`, `if`, or `|`
...
134 | / impl_trait_for_enum!(
135 | |             Animal; Animals => crie() -> String, crie_plusieurs_fois(n: isize) -> String;
136 | |             Dog => Chien,
137 | |             Cat => Chat
138 | |         );
    | |__________- in this macro invocation
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: unexpected end of macro invocation
   --> src/main.rs:105:115
    |
89  | macro_rules! impl_trait_function{
    | -------------------------------- when calling this macro
...
105 |                             $($autre_nom_fonction ($($autre_nom_var : $ autre_type_var),*) $(-> $autre_type_retour)?),*);
    |                                                                                                                   ^ missing tokens in macro arguments

目标是拥有一个对象集合,其中包含实现相同特征的不同对象,而使用类似“Vec< dyn Trait>”的东西,因为有时我必须根据对象制作不同的东西。

我使用枚举和匹配模式的解决方案运行良好,但我正在编写很多类似的代码。这就是我试图通过这些宏来避免的。


我不允许像这样在匹配模式中调用宏:

match self {
                impl_multiple_pattern!($nom_enum;$nom_fonction($($nom_var),*); $($identifiant),*);
            }

我的想法不可能用宏来实现吗?

标签: rustmacros

解决方案


推荐阅读