Есть ли способ сделать рекурсивную структуру / перечисление в штучной упаковке по умолчанию? - PullRequest
0 голосов
/ 31 января 2020

Если я попытаюсь определить рекурсивную структуру / перечисление в Rust:

enum Enum {
    A,
    B(Enum),
    C(Enum, i32),
    D(Enum, Enum),
    ...
}

Я получу ошибку компиляции, как и ожидалось.

Я знаю, что одно из возможных решений этой проблемы заключается в том, чтобы обернуть все рекурсивные ссылки Box<T> следующим образом:

enum Enum {
    A,
    B(Box<Enum>),
    C(Box<Enum>, i32),
    D(Box<Enum>, Box<Enum>),
    ...
}

или даже предоставить псевдоним type:

type Enum = Box<InnerEnum>;    

enum InnerEnum {
    A,
    B(Enum),
    C(Enum, i32),
    D(Enum, Enum),
    ...
}

Это заставило меня задуматься, возможно ли сделать это автоматически как-нибудь? У меня есть такой макрос?

#[boxed]
enum Enum {
    A,
    B(Enum),
    C(Enum, i32),
    D(Enum, Enum),
    ...
}

1 Ответ

1 голос
/ 31 января 2020

Я настоятельно рекомендую придерживаться классического c подхода явного выписывания всего перечисления.

Но - что касается вашего вопроса о возможности - я думаю, что это можно сделать (в определенной степени) :

macro_rules! boxed_enum{
    ($dummy: ident, enum $E: ident $($variant:tt)* ) => {
        pub mod $dummy {
            type $E = Box<$dummy>;
            pub enum $dummy $($variant)*
        }
        type $E = $dummy::$dummy;
    }
}

boxed_enum!(InnerEnum, enum Enum {
    A,
    B(Enum),
    C(Enum, i32),
    D(Enum, Enum),
});

Макрос принимает $dummy, который является как именем вспомогательного mod файла, так и вспомогательного enum (как описано в вашей уловке), и псевдонимами типа для фиктивного -enum к желаемому идентификатору.

Я думаю, что можно сгенерировать $dummy из $E, чтобы пользователю не нужно было указывать это явно. Однако это будет зависеть от concat_idents (iir c, только на ночь) или других ящиков, таких как paste.

Как уже говорилось, в этом случае я бы go с ручным решением .

...