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.

Reply via email to