Dear all,
Today I tried out the new generics support in Go for the first time by implementing Dijkstra's algorithm for the shortest path in a directed graph. In case it's interesting to somebody, here are my impressions, code is at
https://github.com/seehuhn/go-dijkstra .
The key parts of my code are:
type Vertex[edge any] interface {
comparable
Edges() []edge
}
type Edge[vertex any, length constraints.Ordered] interface {
From() vertex
To() vertex
Length() length
}
func ShortestPath[edge Edge[vertex, length], vertex Vertex[edge], length constraints.Ordered](start, end vertex) ([]edge, error) { ...}
My comments/questions:
- I found generics reasonably easy to use. This was my first experience with generics, and I went wrong only once. Overall, writing the code was straightforward.
- Since I am using the beta release, I have to type "go1.18beta2" to call go. Sometimes I typed "go" accidentally, and I found the resulting error messages often confusing and unhelpful. For example, "go test" says "package constraints is not in GOROOT". I wonder whether in case of errors the go command should show a message if the go version in go.mod is newer than the current version.
- "go doc" is still sometimes confused about generics. When I type "go1.18beta2 doc seehuhn.de/go/dijkstra Vertex" the output claims that Vertex "has unexported methods". The message is misleading, it is cause by Vertex embedding "comparable". Is this worth reporting as a bug?
- To me it is not intuitive why "comparable" is built intro the language but "Ordered" is in an external package.
- I have not managed to make it possible for ShortestPath() to automatically infer the type parameters. Is there a trick I have missed?
- Currently I am using constraints.Ordered for the edge length. This currently works, but I'm slightly cheating here since I am also using "+" on the edge lengths. If in the future new ordered types were added to constraints.Ordered, my code might break. Is there a way to say "I need <= and +" (short of enumerating all types)?
- When checking for negative edge lengths, I need the zero value for my instance of constraints.Ordered. Currently I am using a separate, uninitialised variable for this. Is there a better way to say "x <= 0" when x is of a type which matches constraints.Ordered?
- I needed to reverse a slice in-place. Would a function to do this make a good addition to golang.org/x/exp?
- The "func ShortestPath..." line is hard to read and quite long. I didn't find a good place for a line break either. Any ideas for making this more readable?
I'd be happy to receive feedback about my code.
All the best,
Jochen