Forgive me for making a new thread, I felt the older ones had run their course, and I had trouble deciding who to reply to.
I would like to propose a simpler syntax which looks a bit more Go-like (to me) is more terse, has no ambiguity and does not require any new bracket types. Here it goes: // generic type variables are always prefixed by an `@` symbol type Heap(@T) struct { data []@T head, tail uint } // this is how it is instantiated: var myHeapInt Heap@(int) var myHeapSomeType Heap@(SomeType) // No need to specify the type variable in functions, they should just match the declaration. // Easy for the compiler and humans to follow. There's practically no new syntax other // than the generic type specifier. func (h *Heap) Push(v @T) bool { ... } // Complex example with multiple type specifiers. // What if one wants explicit order of instantiation? type S(@V, @U, @T) struct { P1 @T P2 @U P3 @V } // instantiation is always the same syntax var myS S@(int, string, float) // what if attributes are of generic type themselves? // This equates to: S2<S<T, U V>> // which can be simplified to S2<T, U, V> where S<T, U, V> exists type S2(@T, @U, @V) struct { P1 S(@T, @U, @V) } // can be instantiated the usual way var myS2 S2@(int, string, float) // for a function, which constraints are set for the input types func Max(v ...@T) @T where @T: int | uint | int8 | ... | float32 | float64, // T can be of multiple types, which helps to avoid defining a new interface for everything // @V : ... multiple where clauses can be added here for different type variables { ... } //////////////////////////////////////////////////////////////// // // Examples lifted from the official proposal: // //////////////////////////////////////////////////////////////// // Smallest returns the smallest element in a slice. // It panics if the slice is empty. func Smallest(s []@T) @T where @T: Ordered { r := s[0] // panics if slice is empty for _, v := range s[1:] { if v < r { r = v } } return r } // Map calls the function f on every element of the slice s, // returning a new slice of the results. func Map(s []@F, f func(@F) @T) []@T { r := make([]@T, len(s)) for i, v := range s { r[i] = f(v) } return r } // NewPair returns a pair of values of the same type. func NewPair(f1, f2 @F) *Pair(@F) { ... } To me this looks simpler and more clear to read than the official proposal, and practically all other generics syntax that I know of. The `@` symbol will immediately signal `generic type` to the reader, there isn't too much to type, retype or read. You will also never see a generic type without its `@` prefix anywhere in the code, which significantly helps with readability. It's vague neither to humans nor machines, and can be read as `Heap at int (-land!)` during instantiation which while not idiomatic English, still communicates the purpose. What do you think? -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/a06922a0-c6c5-4ca4-924a-cc9337cb01b9o%40googlegroups.com.