如何表达"切片的类型(字符串或'其他此类切片')"

时间:2017-09-02 10:59:18

标签: go types abstract-syntax-tree algebraic-data-types

我如何在Go中表达一个类型是"(字符串或其他此类列表)的列表"?基本上是好的' "树表示为无限嵌套的列表列表和某些值(本例中的字符串)"

我正在寻找一个S表达式的最简单的表示形式(它本身就是最简单的AST),在Python中看起来像这样:

  glVertex3f(20.0, 20.0, 0.0);
  glVertex3f(80.0, 20.0, 0.0);
  glVertex3f(80.0, 80.0, 0.0);
  glVertex3f(20.0, 80.0, 0.0);

这些表达式在Go中有哪些类型?显然sexp1 = ["+", "x", "y", ["*", "10", "myVal"]] sexp2 = ["foo" "bar" "baz"] sexp3 = [ [ [["gooo"], "moo"] ], "too", ["yoo", "2"] ] 不起作用,因为这不起作用:

[][]string

(编译错误:1。func makeSexp(parserName string, values ...[][]string) [][]string { return append([]string{parserName}, values...) } ,2。cannot use values (type [][][]string) as type []string in append。)

...虽然完全无类型的版本有效(但我不想完全放弃类型安全!):

cannot use append([]string literal, values...) (type []string) as type [][]string in return argument

1 个答案:

答案 0 :(得分:5)

不幸的是,Go不支持代数数据类型,所以最好将其设置为类型安全的是创建一个未导出的接口,并进行两次实现:

type sExp interface {
    sExp()
}

type s string

func (s) sExp() {}

type l []sExp

func (l) sExp() {}

// ...
var sexp1 sExp = l{s("+"), s("1"), s("2"), l{s("*"), s("10"), s("myVal")}}

这基本上是Protobuf编译器处理的例子。 oneof个案例。这仍然需要很多类型的开关或类型断言才能使用,但至少你可以确定你的模块之外的任何东西都不能修补它。

游乐场:https://play.golang.org/p/KOvFqJEvxZ