Деструктурировать перечисление ржавчины без сопоставления

Как правильно упростить этот странный код? Не существует варианта AstNode, который не обертывал бы внутреннюю структуру.

impl<'a> Debug for AstNode<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            AstNode::Literal(inner) => inner.fmt(f),
            AstNode::Variable(inner) => inner.fmt(f),
            AstNode::Binary(inner) => inner.fmt(f),
            AstNode::Unary(inner) => inner.fmt(f),
            AstNode::Call(inner) => inner.fmt(f),
            AstNode::Function(inner) => inner.fmt(f),
            AstNode::If(inner) => inner.fmt(f),
            AstNode::While(inner) => inner.fmt(f),
            AstNode::Begin(inner) => inner.fmt(f),
            AstNode::Assign(inner) => inner.fmt(f),
            AstNode::NewGlobal(inner) => inner.fmt(f),
            AstNode::Error(inner) => inner.fmt(f),
            AstNode::TestAssert(inner) => inner.fmt(f),
            AstNode::TestExpect(inner) => inner.fmt(f),
        }
    }
}

Моя рекомендация: оставить его. Но если вам нужно: если все inner одного типа, вы можете изменить порядок на struct AstNode { inner: InnerType, typ: AstNodeType } enum AstNodeType { Literal, Variable, … }. Если они имеют разные типы, вы можете использовать inner: Box<dyn InnerType> или enum_dispatch (что вызывает подобное поведение через макросы). Хотя, почему бы просто не использовать #[derive(Debug)]?

Caesar 06.02.2023 07:20

@Caesar #[derive(Debug)] добавит имя перечисления.

Chayim Friedman 06.02.2023 09:09

Я знаю. Но мне интересно, если это нежелательно.

Caesar 06.02.2023 09:31

@ChayimFriedman Да, я пытаюсь это скрыть. Я заглянул в enum_dispatch, но решил, что может быть лучше сначала написать все самому, плюс ни одно из этих перечислений неизвестно во время компиляции, поэтому, вероятно, они не выиграют от огромных оптимизаций, которые они обещают.

jzimmerman 06.02.2023 15:27

Относительный пост stackoverflow.com/questions/60379893/…

samsong8610 07.02.2023 06:29
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
5
60
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если элемент inner не зависит от варианта перечисления, нет необходимости помещать его в перечисление. Вы можете продвигать его, поэтому не будет необходимости сопоставлять его. Что-то в этом роде:

struct AstNode(AstKind, InnerType);

enum AstKind {
  Literal,
  Variable,
  ...
}

тогда вы можете написать:

impl<'a> Debug for AstNode<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.1.fmt(f)
    }
}

В этой системе типов явно указано, что InnerType и AstKind независимы. В вашем случае, если я правильно понимаю.

Это здорово и будет хорошо работать. К сожалению, в моем случае не стоит рефакторить все остальное, но это, вероятно, лучшее решение. Спасибо!

jzimmerman 07.02.2023 19:38

Другие вопросы по теме