|
|
|
|
|
by staticint
3854 days ago
|
|
Okay, macros. Either way, it provides what most people are asking for in generics (not you, perhaps), even if the implementation isn't exactly pleasant. From a practical standpoint, there really isn't a whole lot of difference in utilizing max (other than the ugliness): # Common pattern in other languages
max<int>(1, 2)
# Similar pattern in Go
#go:generate gofmt -r 'T -> int' -w max.go
max(1, 2)
But yes, "true" generics are much more complicated (and arguably impossible in Go without major changes to the language), I realize. A number of languages that even claim to have generics fall short on that front, which is a path the Go authors have said they do not want to go down.Although you do have me curious how you'd implement max in C in this type-safe way using standard tooling: #define max(a, b) (a > b ? a : b)
...obviously wouldn't fit the bill since it doesn't enforce types like to Go version does. |
|
No, it doesn't. Not even close.
Even something like generic List<T> and sort<T>(List<T>) (separately compiled) will fall down because that simplistic scheme doesn't give each generic type and function a different name, and there's no way for sort<T> to look up whatever name List<T> got instantiated into.
There are also all sorts of hairy issues you will get into when you have name resolution and separate compilation: how do you make sure the macro got instantiated into the same lexical environment that it got declared in? This matters a lot when you have package A exporting a bunch of generic types and functions for package B to use, and it's going to be B doing the expansion using B's types. Even if you set up things just right to resolve the names in the proper lexical scope, how can B's expansion of A's templates use private symbols from A?
Finally, you have the dreaded C++ template error message problems, except they're going to be even worse with this scheme because the compiler is going to complain about code post-textual-replacement, with no way to interpret the chain of events that led to the error. At least clang and GCC have lots of semantic information that they can use, since templates are expanded during semantic analysis.