3 ms·
Some people here seem to not like the similarity to interfaces, but I think, it should be even more like interfaces. In fact, I like the interface syntax even b
by arendtio 7y ago
Some people here seem to not like the similarity to interfaces, but I think, it should be even more like interfaces. In fact, I like the interface syntax even better than the contract syntax. And the type parameter list pollutes the otherwise very clean syntax in my opinion.
So you might ask what I am suggesting. AFAIK there are two major problems preventing interfaces to be used as generics:
1. There is no way to require the methods of builtin types aka operators.
2. Compile-time type safety is very limited
The reason why interfaces have no access to operators and other language features is that the language is kinda rough around the edges. And I really don't want to hurt anybody with this statement. I love the language, but I think there are some things that aren't perfect.
For example, just imagine every array/slice would have a method (e.g. Position(int)) that would be the equivalent of the square brackets and the square brackets would be just some syntactic sugar like
arrayA[0] == arrayA.Position(0)
Same thing for operators like +
x := 1
x + 2 == x.Addition(2)
It would eliminate a lot of cases that make contracts necessary. In essence, it would mean that you could actually address built-in types in interfaces.
The second problem is related to the type parameter list. In my opinion, it would be better to simply put those types on extra lines like:
type T Generic
func Print(s []T) {
// function body
}
I mean, there should be no problem in making them available for more than one function and it would definitely clean up the function signature and look more Go-like.
- baby 7y agoThat looks much better! Somewhat like associated types of rust.
- n13 7y agoAgree & Voted. Another alternative that I would like is to have angle brackets < > for better readability, so that definition and call would look as follows: // 1 func Print2<type T1, T2>(s1 []T1, s2 []T2) { ... } Print2<int,int>( ... ) // 2 var v Vector<int> // 3 func (v *Vector<Element>) Push(x Element) { *v = append(*v, x) } Sorry, if it gives you C++ nightmares.
- atombender 7y agoAgreed, though I think the syntax problem (too many parens) could be made more readable and Go-like by emphasizing the generic aspect and making it stand out visually -- leaving no doubt that you're in a section that's generic, and perhaps dissuading overuse by making it noisy. Perhaps something like: generic func(T, U) Map(slice []T, mapper func(T) U) []U For "contracts": type Set generic interface(T comparable) { Push(T) Pop() T } Every time you want to refer to a generic type you'd have to use the generic keyword, which encourages use of concrete types: type IntSet generic Set(int) This is more or less how Modula-3 does it. Generics have dedicated syntax with a "generic" keyword.