我想在Golang中对AST进行编码/解码,但是遇到了缺少sumtypes的障碍。
一个非常简单的AST来证明这个问题:
data BoolAST = Or BoolAST BoolAST | And BoolAST BoolAST | Lit Bool
方法1
type BoolStatement interface {
ComputeBool() bool
Serialize() []byte
}
type Or struct {
Left BoolStatement
Right BoolStatement
}
type And struct {
Left BoolStatement
Right BoolStatement
}
type BoolFunc struct {
Value bool
}
现在这个结构序列化非常好,但我遇到的麻烦是反序列化(msgpack,json等)。因此,您必须将接口包装在结构中,以便添加反序列化方法。这对我来说也似乎草率,因为我不想手工制作序列化器
方法2
为了解决这个问题,我改变了我的结构。一切都是相同的结构,但一次只填充一个字段。此代码使反序列化变得轻而易举。
type BoolAST struct {
Or []BoolAST
And []BoolAST
Lit bool
}
这很适合反序列化,因为空字段为零,但后来我有这些空字段。解释AST时,我必须使用switch语句来查找哪个字段为空,这会增加一点开销。
这也让json很好看:
{
"and": [
{"lit": true},
{"or": [
{"lit": false},
{"lit": true}}
]
]
}
但是当ast有许多类型的分支路径时,这可能会变得疯狂。你可能最终在结构上有10个无字段。
没有和类型来解决这个问题似乎很难。这是正确的做法吗?