On Tue, Jul 21, 2020 at 9:51 AM Kh Af <kh.afroo...@gmail.com> wrote: > > 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?
Just some quick notes. The @ character seems to move from declaration to instantiation. In the declaration it's a prefix for a type parameter, in an instantiation it introduces a list of type arguments. The "where" clause used for constraints is like nothing else in Go. Using an @ prefix for some identifiers isn't like anything else in Go. In Go all identifiers other than labels share the same namespace and are written the same way. Ian -- 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/CAOyqgcWEiPuYkx2JHD2u-%2BJCNs-%3DWpKGkHfrfT5FZk-oHSUXCA%40mail.gmail.com.