go-inline

Generic Data Structures/Algorithms in golang.

Stars
53

go-inline

Generic Data Structures/Algorithms in golang via code generation (glorified copy&paste).

One might want to use goinline tool to generate specific implementation of generic data structures, such as map, vector, matrix, set. Or to generate specific implementation of generic algorithms, such as sort, binary search.

Goals:

  • Write code once
  • Simple, readable and tested tested go code (e.g. no templates/language extensions)
  • Type safety and speed all the way (e.g. no reflection)
  • No magic, everything is explicit
How-to

Install goinline.

go get github.com/sasha-s/go-inline/goinline/cmd/goinline
Creating a blueprint.

Blueprint is a package that implements a certain generic data type/algorithm.

Let us consider Vector[Number].

package vector

type Number float64

type Vector []Number

func (v Vector) Sum() Number {
    var s Number
    for _, x := range v {
        s += x
    }
    return s
}

func (v Vector) Dot(w Vector) Number {
    var s Number
    for i, x := range v {
        s += x * w[i]
    }
    return s
}
...

Number is a type parameter: we want to be able to use derived versions Vector[float32] or Vector[int].

Note, that Number is a standalone type. This makes it easy to generate the derived versions.

Since we are using + and * the Vector blueprint can be only used with ints and floats.

Have a look at more complete example

Generating derived code.

In case of Vector[Number]:

goinline -package=github.com/sasha-s/go-inline/examples/blueprints/vector --target-package-name=v -target-dir=. -w "Number->int"

This will use a blueprint from package github.com/sasha-s/go-inline/examples/blueprints/vector, looking for the it in $GOPATH, create a generated version in current (.) folder, will rename the package to v and will replace Number with int in the generated code.

Equivalent go:generate directive: //go:generate goinline -package=github.com/sasha-s/go-inline/examples/blueprints/vector --target-package-name=v -target-dir=. -w Number->int

See vector example.

Note, goinline does not check if the blueprint code compiles. Garbage in, garbage out.

Writing tests so they work after inlining types is tricky, so goinline does not generate tests by default.

goinline tool

One could get similar results with some scripting around gofmt -r, given that the blueprints are well-structured.

FAQ
  • Why is there no generics in go?
  • How is it different from
  • copy&paste: c&p is painful to maintain, though if the blueprint is well-structured, the copy&paste is easy.
  • gen: gen works with text/template, goinline starts with working, testable go code, so creating the blueprints is easier and cleaner.
  • goast: goast tries to be smart and infer things, goinline is very explicit. Also, goinline code is shorter and simpler.
  • gotemplate: goinline is more explicit, works with multiple files per blueprint. More details.