Как правильно упростить этот странный код? Не существует варианта 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),
}
}
}
@Caesar #[derive(Debug)]
добавит имя перечисления.
Я знаю. Но мне интересно, если это нежелательно.
@ChayimFriedman Да, я пытаюсь это скрыть. Я заглянул в enum_dispatch, но решил, что может быть лучше сначала написать все самому, плюс ни одно из этих перечислений неизвестно во время компиляции, поэтому, вероятно, они не выиграют от огромных оптимизаций, которые они обещают.
Относительный пост stackoverflow.com/questions/60379893/…
Если элемент 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
независимы. В вашем случае, если я правильно понимаю.
Это здорово и будет хорошо работать. К сожалению, в моем случае не стоит рефакторить все остальное, но это, вероятно, лучшее решение. Спасибо!
Моя рекомендация: оставить его. Но если вам нужно: если все
inner
одного типа, вы можете изменить порядок наstruct AstNode { inner: InnerType, typ: AstNodeType } enum AstNodeType { Literal, Variable, … }
. Если они имеют разные типы, вы можете использоватьinner: Box<dyn InnerType>
или enum_dispatch (что вызывает подобное поведение через макросы). Хотя, почему бы просто не использовать#[derive(Debug)]
?