I have found the generics syntax to be somewhat confusing, too many things look the same and there seem to be too many names involved. I admit I have not been reading all of the suggestions (I simply do not have that much spare time), so forgive me if this has already been proposed.
Start with one of the examples:
contract viaStrings(t To, f From) {
var x string = f.String()
t.Set(string("")) // could also use t.Set(x)
}
What is the point of t and f? Why not simply:
contract viaStrings(To, From) {
string = From.String()
To.Set(string)
}
When using a contract, we have too many ()’s. How about something that doesn’t require as much context to figure out:
func SetViaStrings[bar(A, B)](s []B) []A { … }
Then when using:
var ips []net.IP
a := SetViaStrings[_, []string](ips)
The _ means you can infer the type from the call. If all types can be inferred, as in the proposal:
var ips []net.IP
var a []string
a = SetViaStrings(ips)
I also sort of see a contract as a type, so I would consider:
type viaStrings(t To, f From) contract { … }
Note that this is the only place the term contract needs to be used. There is no reason it needs to be an explicit keyword.
Extending the simplified syntax (I have seen other similar suggestions), assuming all single upper case letters are contract types for demonstrative purposes (e.g., contract Foo(A, B, C))
A.(int) // A is assignable to an int
A.(B) // A is assignable to B
error = A.Foo(B, C) // A has a method Foo that takes a B and C and returns an error
B, error = A(B, C, int) // A is a function that takes a B, C, and an int, returning a B and an error
nil = A // A can be nil
error = A // A implememnts the error interface
!A // A is boolean
A == A // A supports equality
A < A // A supports inequality
A + A // A supports addition
A * A // A supports arithmetic oprations
A % A // A supports modulus
A[:] // A is a slice (maybe just A[])
C = A[B] // A is a map of B to C
_ = A[B] // A is a map of B to anything (maybe just A[B])
B = <- C // C is a channel of B
<- C // C is a channel of anything
len(A) // A has length
cap(A) // A has capacity
That list is probably not exhaustive, but it should be straightforward to extend. The key is that there are no loops, conditions, range statements, etc. It probably requires more work on the parser, but we are optimizing the person reading the source code, right?
Anyhow, I am certainly more in favor of the contract being a series of single lines.