Two thoughts:

1. How useful is it in practice to have separate start and end delimiters? 
 Does it matter for nested declarations?  I didn't see any nested 
declarations in the Draft Design document 
<https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md>,
 
for example.  If allow the same token on both sides, we could use the 
vertical bar, and not require the type keyword at all:

func f(T|int|)

struct{ T|int| }

interface{ T|int| }

[]T|int|{}

type S|T| struct { v T }


(A concrete example is included at the end of this e-mail.)

The above was one of the options Matt McCullough outlined in "Towards 
Clarity: Syntax Changes for Contracts in Go 
<https://gist.github.com/tooolbox/6bde6925a1a8c78cb593b2c11e977b07#non-parenthetical-delimiters>
".

2. Otherwise, could we also consider double square brackets so it becomes 
immediately obvious that the expression has nothing to do with an array? 
 (The type keyword is not needed here either.)

func f(T[[int]])

struct{ T[[int]] }

interface{ T[[int]] }

[]T[[int]]{} 

type S[[T]] struct { v T }


(The same example in this style is included at the end of this e-mail.)


On the whole, I prefer [[...]] over |...| over [...] over (...), but would 
also prefer that type declarations stick out easily enough.

jpap


PS. An example from Matt Layher 
<https://mdlayher.com/blog/go-generics-draft-design-building-a-hashtable/>, 
rewritten using vertical bars:

// Package hashtable implements a basic hashtable for generic key/value pairs.

package hashtable

// A Table is a basic generic hashtable.

type Table|K comparable, V interface{}| struct {

    // hash is a function which can hash a key of type K with t.m.

    hash func(key K, m int) int

        m     int

        table [][]kv|K, V|

}

// A kv stores generic key/value data in a Table.

type kv|K, V| struct {

        Key   K

        Value V

}

// New creates a table with m internal buckets which uses the specified hash

// function for an input type K.

func New|K comparable, V interface{}|(m int, hash func(K, int) int) *Table|K, 
V| {

        return &Table|K, V|{

                hash:  hash,

        m:     m,

                table: make([][]kv|K, V|, m),

        }

}


PPS. The same example from Matt Layher 
<https://mdlayher.com/blog/go-generics-draft-design-building-a-hashtable/>, 
rewritten using [[...]]:

// Package hashtable implements a basic hashtable for generic key/value pairs.

package hashtable

// A Table is a basic generic hashtable.

type Table[[K comparable, V interface{}]] struct {

    // hash is a function which can hash a key of type K with t.m.

    hash func(key K, m int) int

        m     int

        table [][]kv[[K, V]]

}

// A kv stores generic key/value data in a Table.

type kv[[K, V]] struct {

        Key   K

        Value V

}

// New creates a table with m internal buckets which uses the specified hash

// function for an input type K.

func New[[K comparable, V interface{}]](m int, hash func(K, int) int) 
*Table[[K, V]] {

        return &Table[[K, V]]{

                hash:  hash,

        m:     m,

                table: make([][]kv[[K, V]], m),

        }

}


-- 
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/3f0b6dc9-6ff1-4b20-bb09-8ef1aeb688beo%40googlegroups.com.

Reply via email to