How to express the type of "slice (string or" other such slice ")

How can I express in Go a type that is "a list (strings or other such lists)"? Basically, a good "ol" tree is represented as infinitely nested list lists and something like a value (lines in this example) "

I'm looking for the simplest possible representation of an S-expression (which would itself be the simplest of AST), which in Python would look like this:

sexp1 = ["+", "x", "y", ["*", "10", "myVal"]] sexp2 = ["foo" "bar" "baz"] sexp3 = [ [ [["gooo"], "moo"] ], "too", ["yoo", "2"] ] 

What type will all these expressions have in Go? Obviously, the [][]string does not work, since it does not work:

 func makeSexp(parserName string, values ...[][]string) [][]string { return append([]string{parserName}, values...) } 

(Compilation errors: 1. cannot use values (type [][][]string) as type []string in append , 2. cannot use append([]string literal, values...) (type []string) as type [][]string in return argument .)

... while the fully untyped version is working ( but I do not want to completely abandon type safety! ):

 func makeSexp(parserName string, values ...interface{}) interface{} { return append([]interface{}{parserName}, values...) } 
+7
types algebraic-data-types go abstract-syntax-tree
source share
1 answer

Unfortunately, Go does not support types of algebraic data, so it is best to make it type safe - create a non-portable interface and make two implementations of it:

 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")}} 

This mainly concerns Protobuf protocols, for example, oneof . It will still require many types of switches or type statements to work, but at least you can be sure that nothing outside your module can mess with it.

Playground: https://play.golang.org/p/KOvFqJEvxZ .

+5
source share

All Articles