This seems similar to previous proposals based on introducing kind-based type categories for contracts. Putting the kind right there in the arg instead of a separate contract seems like an improvement, keeping it more local to where it is used. Why not just take this one step further and just introduce entirely new types:
* number * slice * map (re-useable from existing use-case?) * etc func Min(x, y number) number { if x < y { return x } return y } func Delete(sl *slice, idx int) { *sl = append((*sl)[:idx], (*sl)[idx+1:]) } The compiler would just do its normal thing based on whatever actual kind you pass in — an implicit type switch basically.. You could convert any `number` into a specific type (e.g., float64) when you need to, and if you passed two different underlying types of numbers as args to Min, it would automatically up-convert to the one with highest precision. Essentially, this is undoing all the strict type specificity of Go, and making it work like C, or Python.. This minimalist approach avoids all the complexity and ugliness of parameterizing types etc — it is just a more generic type of type, and is more or less how the generic builtin operators and functions like len, copy, etc already work on their respective kinds. Composite types seem like they might even just work without a type parameter: type Vec2 struct { X, Y number } func (u Vec2) Add(v Vec2) Vec2 { return Vec2{u.X + v.X, u.Y + u.Y} } In summary, this is really just introducing a very controlled dose of dynamic typing into the language (adding a dash of Python into Go). Probably this has already been considered and rejected hundreds of times over the course of these discussions, but I’ve lost track, and seems at least like a very simple conceptual proposal: you can achieve a lot of generics functionality by just introducing dynamic typing. Syntactically and conceptually, it is far cleaner and simpler than anything else I’ve seen in the generics discussion, at least. - Randy > On May 31, 2019, at 6:52 AM, Michal Strba <faiface2...@gmail.com> wrote: > > @Ian, I have been thinking and I’ve come up with a possible solution to yours > and some other problems. I’d love to hear your thoughts on it. Note, that > this is a very fresh idea. > > I’m addressing two problems here: > > • Inability to do Min/Max and other generic numeric functions. > • There are a few kinds of generic parameters, but the kind is always > implicit. This can be a problem because changing the body of a function can > result in a backward-incompatible change, even when the signature remains the > same. > Here are the ideas (also described in the proposal now, in the section called > ‘Further ideas’). > > The kind of a generic parameters is currently completely implicit. Some > annotation could be added. One possible syntax could be like this: > > • gen n for generic array lengths. > • gen T for arbitrary types (convertible to interface{}). > • gen eq T for equalable types (comparable with == and usable as map > keys). > • gen num T for numeric types (with operators like +, -, <, …). > Array lengths and arbitrary types can have the same notation because it’s > always possible to distinguish them by context. Alternatively, they could be > distinguished by capitalization (lower-case for array lengths, upper-case for > types). > > Syntax-wise, eq and num would not be keywords on their own. Rather, gen eq > and gen num would be two-word keywords. > > The syntax is rather ad-hoc, I admit. It’s a very fresh idea, completely open > to refinement. However, since there are only four cases, an ad-hoc syntax may > actually be the right choice. > > It’s also easily extensible with new possible “contracts”, but I’d generally > advise against that. > > The addition of the num restriction would actually enable many cool things. > First, the Min/Max functions: > > func > Min(x, y gen num T) T { > > if > x < y { > > return > x > } > > return > y > } > > It would also be useful for generic math types, like vector and matrices. The > matrix example above uses float64, but it could be generalized to all numeric > types. > > As an example, let’s take a look at a possible implementation of a 2D vector > type: > > type Vec2(T) struct > { > X, Y T > } > > There are no restrictions specified in the type definition. This is because > it’s methods and functions that require restrictions, not the types > themselves. For example, this String method requires no restrictions: > > func (u Vec2(gen T)) String() string > { > > return fmt.Sprintf("(%v, %v)" > , u.X, u.Y) > } > > This Eq method requires the types to be comparable with ==: > > func (u Vec2(gen eq T)) Eq(v Vec2(T)) bool > { > > return > u.X == v.X && u.Y == v.Y > } > > But, this Add method requires the types to be numeric: > > func > (u Vec2(gen num T)) Add(v Vec2(T)) Vec2(T) { > > return > Vec2(T){u.X+v.X, u.Y+v.Y} > } > > Consequently, Vec2([]float64) would only have the String method, Vec2(string) > would have the Eq method in addition, and Vec2(float64), Vec2(int32), and so > on, would have all the methods. > > Yes, the idea basically is to introduce two "contracts" into the system. > However, there's no ability to create own contracts and the syntax is very > concise and non-disruptive. I believe this would really cover the vast > majority of use-cases. > > > pi 31. 5. 2019 o 14:05 <fge...@gmail.com> napísal(a): > On 5/31/19, Nick Keets <nick.ke...@gmail.com> wrote: > ... > > This proposal is very interesting and seems to fit nicely into Go, with > > minimal disruption. And speaking personally, it would cover 99% of my needs > > for generics (I'm not that interested in Min/Max, but writing functions to > > get map keys gets old fast). > Interesting, could you please share the problems where the usual > iterating idiom is not good enough? > > -- > 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/CA%2Bctqro9o-RAa6QRVCEQ%2BPu_tre%2BCtJQZaP4LbBTB_6LQntWyg%40mail.gmail.com. > For more options, visit https://groups.google.com/d/optout. > > -- > 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/CAO6k0usrzSrh1j-xboqtxh8jJCz0eRDpfvTggfgi-0%3D10XhNoA%40mail.gmail.com. > For more options, visit https://groups.google.com/d/optout. -- 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/620B9994-BC16-471A-A471-592588AEDF93%40gmail.com. For more options, visit https://groups.google.com/d/optout.